Стоит ли блокировать строки в моей облачной БД, пока они редактируются пользователем

12

Я создаю настольное приложение, которое сохраняет данные в облаке. Одна из проблем, с которой я столкнулся, - это начать редактирование элемента в приложении и на некоторое время оставить его, что приведет к устареванию данных. Очевидно, это также может произойти, если 2 человека пытаются редактировать один и тот же элемент одновременно. Когда они закончат редактирование и захотят сохранить данные, мне нужно либо перезаписать то, что в данный момент существует в базе данных, либо проверить, что они начали редактирование после последнего изменения, либо вынудить их отказаться от своих изменений или, возможно, дать им возможность рисковать. переписывая чужие изменения.

Я думал о добавлении полей is_lockedи lock_timestampв таблицу БД. Когда пользователь начинает редактировать элемент, строка изменится is_lockedна true и установит метку времени блокировки на текущее время. Тогда у меня будет некоторое время, в течение которого блокировка удерживается (например, 5 минут). Если кто-либо попытается изменить элемент, он получит сообщение о том, что элемент заблокирован и когда срок действия блокировки автоматически истечет. Если пользователь уходит, когда редактирование блокировки автоматически истекает через относительно короткий период времени, и после этого пользователь будет предупрежден о том, что срок действия блокировки истек, и будет вынужден возобновить редактирование после обновления данных.

Будет ли это хорошим методом предотвращения перезаписи устаревших данных? Это излишне (я не ожидаю, что приложение будет использоваться более чем несколькими людьми одновременно на одной учетной записи).

(Еще одна проблема, которую я имею, это то, что 2 человека получают блокировку для одного и того же предмета, однако я считаю, что это условие гонки, с которым мне удобно.)

yitzih
источник
1
«У меня есть еще одна проблема - 2 человека получают блокировку для одного и того же предмета, однако я считаю, что это условие гонки, с которым мне удобно» - использование транзакции базы данных вокруг получения блокировки должно предотвратить такие условия гонки.
Жюль
Большинство механизмов баз данных (по крайней мере реляционного типа) имеют встроенную поддержку для этого. Это очень распространенная концепция в мире СУБД, и даже «игрушечные» базы данных справляются с ней достаточно хорошо, учитывая, что вы говорите, что хотите оптимистическую или пессимистическую блокировку. В любом случае, я не думаю, что вам нужно что-то создавать самостоятельно: проверьте параметры вашего движка БД, чтобы узнать, как с ним работать.
jleach
Тот факт, что ваше приложение является настольным ( толстый клиент ), не имеет большого значения. Он может быть спроектирован так же, как и высокодоступное серверное приложение с несколькими экземплярами.
Хосам Али

Ответы:

19

Здесь вам поможет терминология. То, что вы здесь описываете, называется «пессимистическая блокировка». Основной альтернативой этому подходу является «оптимистическая блокировка». При пессимистической блокировке каждый участник должен заблокировать запись перед ее обновлением и снять блокировку после завершения обновления. При оптимистической блокировке вы предполагаете, что никто не обновляет запись, и пытаетесь. Обновление не выполняется, если запись была изменена каким-либо другим актером.

Оптимистическая блокировка, как правило, предпочтительна, если вероятность того, что два актера одновременно обновят одно и то же, невелика. Пессимистичный тип обычно используется, когда этот шанс высок, или вам нужно знать, что ваше обновление сможет быть успешным до вашего запуска. По моему опыту, оптимистическая блокировка почти всегда предпочтительнее, потому что есть много проблем, присущих пессимистической блокировке. В вашем вопросе затронута одна из самых больших проблем. Пользователи могут заблокировать запись для редактирования и затем уйти на обед. Ваше смягчение поможет в этом, но пользовательский опыт будет не лучше, чем оптимистичный подход и, вероятно, будет намного хуже. Например, один пользователь открывает запись, начинает ее обновлять, и его босс появляется за столом. Другой пользователь пытается отредактировать запись. Заперто. Второй пользователь продолжает пытаться и через 5 минут, срок действия блокировки истекает, и второй пользователь обновляет запись. Первый пользователь возвращается к экрану, пытается сохранить и ему сообщают, что он потерял свою блокировку. Теперь в том же сценарии со всем тем же, за исключением использования оптимистической блокировки, опыт первого пользователя почти такой же, но второй пользователь не ждет 5 минут.

Схема, которую вы выложите, была бы значительно улучшена за счет реализации оптимистической блокировки для значения блокировки, но я догадываюсь, что оптимистическая блокировка, вероятно, в порядке, и вы можете избавиться от поля is_locked.

Вы не указываете, какую «облачную БД» вы используете. Вам, вероятно, следует изучить особенности этого, чтобы увидеть, есть ли встроенные функции для этого, прежде чем внедрять собственное решение.

Вот основной рецепт: вместо поля is_locked есть поле номера версии. Когда вы извлекаете запись, вы извлекаете текущую версию записи. При обновлении вы делаете обновление зависящим от поля версии, совпадающего с полученным, и увеличиваете его в случае успеха. Если версия не совпадает, обновление не имеет эффекта, и вы сообщаете об этом как об ошибке.

JimmyJames
источник
Это очень полезный ответ. Можете ли вы объяснить, почему пессимистическая блокировка не рекомендуется, когда существует небольшая вероятность «столкновений». Это просто потому, что для перехода к редактированию требуется обращение к базе данных, или из-за дополнительной сложности или по какой-то другой причине? Благодарность!
Ицих
3
@yitzih Некоторые предложили прочитать: Фаулер и др., Шаблоны архитектуры корпоративных приложений . Есть целая глава по этому вопросу, с хорошим обсуждением всех вариантов и причин их выбора.
Жюль
2
@ Джимми - Твой ответ в порядке. В некоторых случаях сообщение об ошибке обратно может оказаться недостаточным. Рассмотрим случай, когда пользователь тратит несколько минут на обновление записи. В этом случае просто неудача может оказаться недостаточно хорошей, возможно, вы захотите дать пользователю возможность объединить свои изменения в полете с изменениями, совершенными другим пользователем. Я должен был сказать, что оптимистическая блокировка может потребовать разрешения конфликтов в зависимости от ваших требований.
Джон Рейнор
3
Стоит отметить, что пессимистическую блокировку гораздо проще объяснить клиенту. Если вы пишете сообщение о том, что клиент не может получить доступ к записи, потому что она в данный момент редактируется другой, клиент понимает и понимает, и в целом принимает ее. Если вы вместо этого скажете клиенту после сохранения, что сохранение было невозможно, потому что оно уже было обновлено другим пользователем, 7/10, клиент будет разочарован и / или ожидает объяснений этого странного поведения программы.
Нил
2
@Neil Это правда, и я думаю, что это часто, почему пессимистическая блокировка используется, когда оптимистический подход более уместен. Часто рабочий процесс делает очень маловероятным, что происходит столкновение.
JimmyJames
0

Из ответа @ JimmyJames мы можем видеть, как на самом деле вопрос касается взаимодействия с пользователем .

Все зависит от контекста. Сколько времени и усилий требуется для обновления записи? Как часто несколько пользователей хотят обновить один и тот же документ?

Например, если ваши пользователи обычно тратят несколько секунд на обновление записи и при этом возникает небольшое количество споров, то, вероятно, лучше использовать оптимистическую блокировку. В худшем случае пользователю потребуется потратить еще несколько секунд, может быть, до минуты, чтобы обновить документ.

Если ваш документ очень спорный, но хорошо структурированный, возможно, вы можете позволить им блокировать отдельные поля с 30-секундным шагом, показывая таймер или ненавязчивое уведомление, чтобы позволить им расширить блокировку.

Однако, если ваши пользователи тратят значительное количество времени или усилий, вам следует рассмотреть другие подходы. Ваша запись хорошо структурирована? Не могли бы вы показать пользователям сравнение (разницу) между версией на сервере и версией, которую они пытаются сохранить? Можете ли вы выделить различия? Можете ли вы позволить им объединить изменения? Подумайте об опыте, который вы хотите получить с вашими инструментами контроля версий. Вы действительно не хотите, чтобы вас снова писали весь этот код!

Вы можете посмотреть на Google Docs для дополнительного вдохновения. Возможно, вы сможете показать пользователям уведомление о том, что новая версия была сохранена. Может быть, вы можете показать им, как многие люди имеют записи открытой, так что они могут выбрать, чтобы вернуться на менее спорное время.

Хосам Али
источник