Я создаю настольное приложение, которое сохраняет данные в облаке. Одна из проблем, с которой я столкнулся, - это начать редактирование элемента в приложении и на некоторое время оставить его, что приведет к устареванию данных. Очевидно, это также может произойти, если 2 человека пытаются редактировать один и тот же элемент одновременно. Когда они закончат редактирование и захотят сохранить данные, мне нужно либо перезаписать то, что в данный момент существует в базе данных, либо проверить, что они начали редактирование после последнего изменения, либо вынудить их отказаться от своих изменений или, возможно, дать им возможность рисковать. переписывая чужие изменения.
Я думал о добавлении полей is_locked
и lock_timestamp
в таблицу БД. Когда пользователь начинает редактировать элемент, строка изменится is_locked
на true и установит метку времени блокировки на текущее время. Тогда у меня будет некоторое время, в течение которого блокировка удерживается (например, 5 минут). Если кто-либо попытается изменить элемент, он получит сообщение о том, что элемент заблокирован и когда срок действия блокировки автоматически истечет. Если пользователь уходит, когда редактирование блокировки автоматически истекает через относительно короткий период времени, и после этого пользователь будет предупрежден о том, что срок действия блокировки истек, и будет вынужден возобновить редактирование после обновления данных.
Будет ли это хорошим методом предотвращения перезаписи устаревших данных? Это излишне (я не ожидаю, что приложение будет использоваться более чем несколькими людьми одновременно на одной учетной записи).
(Еще одна проблема, которую я имею, это то, что 2 человека получают блокировку для одного и того же предмета, однако я считаю, что это условие гонки, с которым мне удобно.)
источник
Ответы:
Здесь вам поможет терминология. То, что вы здесь описываете, называется «пессимистическая блокировка». Основной альтернативой этому подходу является «оптимистическая блокировка». При пессимистической блокировке каждый участник должен заблокировать запись перед ее обновлением и снять блокировку после завершения обновления. При оптимистической блокировке вы предполагаете, что никто не обновляет запись, и пытаетесь. Обновление не выполняется, если запись была изменена каким-либо другим актером.
Оптимистическая блокировка, как правило, предпочтительна, если вероятность того, что два актера одновременно обновят одно и то же, невелика. Пессимистичный тип обычно используется, когда этот шанс высок, или вам нужно знать, что ваше обновление сможет быть успешным до вашего запуска. По моему опыту, оптимистическая блокировка почти всегда предпочтительнее, потому что есть много проблем, присущих пессимистической блокировке. В вашем вопросе затронута одна из самых больших проблем. Пользователи могут заблокировать запись для редактирования и затем уйти на обед. Ваше смягчение поможет в этом, но пользовательский опыт будет не лучше, чем оптимистичный подход и, вероятно, будет намного хуже. Например, один пользователь открывает запись, начинает ее обновлять, и его босс появляется за столом. Другой пользователь пытается отредактировать запись. Заперто. Второй пользователь продолжает пытаться и через 5 минут, срок действия блокировки истекает, и второй пользователь обновляет запись. Первый пользователь возвращается к экрану, пытается сохранить и ему сообщают, что он потерял свою блокировку. Теперь в том же сценарии со всем тем же, за исключением использования оптимистической блокировки, опыт первого пользователя почти такой же, но второй пользователь не ждет 5 минут.
Схема, которую вы выложите, была бы значительно улучшена за счет реализации оптимистической блокировки для значения блокировки, но я догадываюсь, что оптимистическая блокировка, вероятно, в порядке, и вы можете избавиться от поля is_locked.
Вы не указываете, какую «облачную БД» вы используете. Вам, вероятно, следует изучить особенности этого, чтобы увидеть, есть ли встроенные функции для этого, прежде чем внедрять собственное решение.
Вот основной рецепт: вместо поля is_locked есть поле номера версии. Когда вы извлекаете запись, вы извлекаете текущую версию записи. При обновлении вы делаете обновление зависящим от поля версии, совпадающего с полученным, и увеличиваете его в случае успеха. Если версия не совпадает, обновление не имеет эффекта, и вы сообщаете об этом как об ошибке.
источник
Из ответа @ JimmyJames мы можем видеть, как на самом деле вопрос касается взаимодействия с пользователем .
Все зависит от контекста. Сколько времени и усилий требуется для обновления записи? Как часто несколько пользователей хотят обновить один и тот же документ?
Например, если ваши пользователи обычно тратят несколько секунд на обновление записи и при этом возникает небольшое количество споров, то, вероятно, лучше использовать оптимистическую блокировку. В худшем случае пользователю потребуется потратить еще несколько секунд, может быть, до минуты, чтобы обновить документ.
Если ваш документ очень спорный, но хорошо структурированный, возможно, вы можете позволить им блокировать отдельные поля с 30-секундным шагом, показывая таймер или ненавязчивое уведомление, чтобы позволить им расширить блокировку.
Однако, если ваши пользователи тратят значительное количество времени или усилий, вам следует рассмотреть другие подходы. Ваша запись хорошо структурирована? Не могли бы вы показать пользователям сравнение (разницу) между версией на сервере и версией, которую они пытаются сохранить? Можете ли вы выделить различия? Можете ли вы позволить им объединить изменения? Подумайте об опыте, который вы хотите получить с вашими инструментами контроля версий. Вы действительно не хотите, чтобы вас снова писали весь этот код!
Вы можете посмотреть на Google Docs для дополнительного вдохновения. Возможно, вы сможете показать пользователям уведомление о том, что новая версия была сохранена. Может быть, вы можете показать им, как многие люди имеют записи открытой, так что они могут выбрать, чтобы вернуться на менее спорное время.
источник