Как реализовать пессимистическую блокировку в веб-приложении php/mysql?

Как реализовать пессимистическую блокировку в веб-приложении php/mysql?

  1. веб-пользователь открывает страницу для редактирования одного набора данных (строки)
  2. веб-пользователь нажимает кнопку «заблокировать», чтобы другие пользователи могли читать, но не записывать этот набор данных.
  3. веб-пользователь вносит некоторые изменения (занимает от 1 до 30 минут)
  4. веб-пользователь нажимает «сохранить» или «отменить», и «блокировка» снимается

Существуют ли стандартные методы в php/mysql для этого сценария? Что произойдет, если веб-пользователь никогда не нажимает «сохранить»/«отменить», а закроет интернет-обозреватель?


person user1027167    schedule 17.11.2011    source источник


Ответы (3)


Традиционно это делается с помощью логического столбца locked в записи базы данных, которая помечена соответствующим образом.

Функция такого рода блокировки заключается в том, что блокировка должна быть снята, и обстоятельства могут помешать этому произойти естественным путем (системные сбои, глупость пользователя, потерянные сетевые пакеты и т. д. и т. д. и т. д.). Вот почему вам нужно будет предоставить какой-то метод ручной разблокировки и / или установить ограничение по времени (возможно, с помощью задания cron?) на то, как долго запись может быть заблокирована. Вы могли бы реализовать какой-то опрос AJAX, чтобы сохранить запись заблокированной, если браузер все еще открыт? В любом случае, вам, вероятно, лучше всего проверить, что данные в записи такие же, как и при получении блокировки, прежде чем изменять ее.

Это ограничение такого типа поведения особенно распространено в веб-приложениях, но верно и для всего, что использует этот подход - Sage Line 50, например, является ошибкой для него, мне регулярно приходится удалять файлы блокировки после сбоя машины/приложения.

person DaveRandom    schedule 17.11.2011

Вам необходимо реализовать поля LOCKDATE и LOCKWHO в вашей таблице. Я сделал это во многих приложениях за пределами PHP/Mysql, и это всегда одно и то же.

Блокировка прекращается, когда TTL проходит, поэтому вы можете выполнить вычитание дат, используя NOW и LOCKDATE, чтобы увидеть, был ли объект заблокирован более 30 минут или 1 часа, как вы хотите.

Другим фактором является рассмотрение того, является ли текущий пользователь тем, кто блокирует объект. Вот почему вам также нужен LOCKWHO. Это может быть user_id из вашей базы данных, session_id из PHP. Но придерживайтесь того, что идентифицирует пользователя, IP-адрес - не лучший способ сделать это.

Наконец, всегда думайте о функции массовой разблокировки, которая просто сбрасывает все LOCKDATE и LOCKWHO...

Ваше здоровье

person Mathieu Dumoulin    schedule 17.11.2011
comment
Также обратите внимание, что оптимистическая блокировка также является хорошим способом работы, вы можете реализовать оптимистическую блокировку с помощью простого столбца LASTUPDATE и сравнить его с последним значением LASTUPDATE, которое у вас есть в HIDDEN FIELD. Если данные изменились, вы заставляете пользователя признать, что он должен перезапустить свое редактирование, или вы можете попробовать и посмотреть, хотите ли вы сделать страницу MERGE, чтобы показать новый и старый контент для сравнения пользователем. - person Mathieu Dumoulin; 17.11.2011
comment
Я рассматривал что-то очень похожее на LOCKDATE и LOCKWHO, упомянутые выше. Вы когда-нибудь задумывались об использовании запроса jQuery/Ajax для обновления поля LOCKDATE (из представления редактирования), пока пользователь работает над редактированием? - person jjwdesign; 22.02.2013
comment
Я бы не стал реализовывать средство обновления блокировки jquery, потому что, если по какой-либо причине ваш пользователь в конечном итоге забудет открыть свой браузер, и кому-то нужно отредактировать объект, время ожидания никогда не истечет. Предоставление разумного TTL для вашей блокировки - действительно метод выбора. - person Mathieu Dumoulin; 22.02.2013
comment
Нужно самостоятельное кодирование для реализации пессимистической блокировки в веб-приложении, без какого-либо простого вызова функции в существующей среде? - person user1169587; 23.01.2019
comment
Я уверен, что вы можете найти фреймворк, в котором эта функция будет либо встроенной, либо через плагин, но, учитывая, что это было написано в 2013 году, вы можете пересмотреть необходимость блокировки. Общее поведение приложений сегодня заключается в использовании шаблонов ReST, и они не очень хороши для пессимистичной блокировки, может быть, в некоторой степени оптимистичны, но не пессимистичны. - person Mathieu Dumoulin; 25.01.2019

Я бы написал блокировки в одной централизованной таблице вместо того, чтобы добавлять поля во все таблицы.

Пример структуры таблицы:

tblLocks

  • TableName (Имя заблокированной таблицы)
  • RowID (первичный ключ заблокированной строки таблицы)
  • LockDateTime (когда строка была заблокирована)
  • LockUser (Кто заблокировал строку)

При таком подходе вы можете найти все блокировки, сделанные пользователем, без необходимости сканировать все таблицы. Например, вы можете снять все блокировки, когда пользователь выходит из системы.

person Benoit Gauthier    schedule 11.09.2013