Каков наилучший способ убедиться, что два человека не редактируют одну и ту же строку в моем веб-приложении?
У меня есть приложение PHP/jQuery/AJAX/MySQL, созданное для управления базами данных. Я хочу реализовать возможность предотвратить одновременное редактирование одной и той же строки базы данных несколькими пользователями.
- Что называется?
- Использую ли я систему токенов, и кто когда-либо имеет токен, может редактировать его до тех пор, пока они не выпустят токен?
- Я использую "последнюю дату/время редактирования", чтобы сравнить загрузку формы HTML со временем в базе данных, и если база данных является наиболее resent edit, то она предупреждает вас?
- Я блокирую строку, используя функции базы данных?
Я просто не уверен, что лучше. Предполагая, что между 10 - 15 одновременными пользователями
Ответы
Ответ 1
Существует два общих подхода: оптимистическая и пессимистическая блокировка.
Оптимистическая блокировка, как правило, намного проще реализовать в веб-среде, потому что она принципиально без гражданства. Он также намного лучше. Недостатком является то, что предполагается, что ваши пользователи обычно не будут пытаться редактировать один и тот же набор строк одновременно. Для большинства приложений это очень разумное предположение, но вам нужно будет проверить, что ваше приложение не является одним из факторов, когда пользователи будут регулярно наступать друг на друга. В оптимистичной блокировке у вас будет какой-то столбец last_modified_timestamp
, который вы бы SELECT
, когда пользователь извлекал данные, а затем использовал в предложении WHERE
при обновлении даты, т.е.
UPDATE table_name
SET col1 = <<new value>>,
col2 = <<new values>>,
last_modified_timestamp = <<new timestamp>>
WHERE primary_key = <<key column>>
AND last_modified_timestamp = <<last modified timestamp you originally queried>>
Если это обновляет 1 строку, вы знаете, что вы были успешны. В противном случае, если он обновляет 0 строк, вы знаете, что кто-то еще модифицировал данные в промежутке времени, и вы можете предпринять некоторые действия (обычно показываете пользователю новые данные и спрашиваете их, хотят ли они перезаписать, но вы можете использовать другие подходы к разрешению конфликтов).
Пессимистическая блокировка более сложна для реализации, особенно в веб-приложении, особенно когда пользователи могут закрыть свой браузер без выхода из системы или когда пользователи могут начать редактировать некоторые данные и пойти на обед перед тем, как нажать Submit
. Это усложняет масштабирование и, как правило, затрудняет администрирование приложения. На самом деле стоит только подумать, будут ли пользователи регулярно пытаться обновлять одни и те же строки или обновлять строку занимает большое количество времени для пользователя, поэтому стоит сообщить им, что кто-то заблокировал строку.
Ответ 2
Я собирался реализовать это в одной из моих собственных систем.
Вы можете создавать новые столбцы в своей базе данных записей, называемых timelocked.
Когда запись открывается, вы должны установить запись, которую они открывают, для расписания на текущее время. Во время редактирования записи отправляйте keepalive обратно на сервер через ajax каждые 2 минуты. При отправке keepalive сервер будет увеличивать время с таймером до текущего времени отправки запроса и, следовательно, четвертого (это будет иметь смысл в секунду). Когда пользователь закончит редактирование, установите timelocked в false.
Теперь, если кто-то пошел открывать запись, которая уже открыта, php проверит -
если timelocked == false - означает, что он не редактируется,
в противном случае запись может редактироваться, но что, если пользователь закрыл окно своего браузера. что используется keepalive.
если разница между текущим временем и timelocked больше, чем 2 минуты, это означает, что они больше не ожидают редактирования, что позволит вам открыть его.
Надеюсь, вы все это поймете.
Ответ 3
Не пытайтесь предотвратить это. Пусть они решат, что делать в случае конфликта изменений.
Добавьте метку времени в таблицу. Сравните временную метку, когда строка была восстановлена с текущей меткой времени. Сообщите им об изменениях между их загрузкой и их сохранением и дайте им возможность решить, какое действие нужно предпринять.
Итак, да, номер 3.
Ответ 4
Я лично не помешал бы этому. Если бы это было требование задания, я бы отслеживал текущее/последнее известное местоположение пользователей и запретил кому-то редактировать одну и ту же строку, которую кто-то редактирует таким образом. Я видел, как люди добавляли строку в таблицу, говорящую isLocked или isBeingWorkedOn и т.д., Но я видел, что этот тип системы терпит неудачу намного чаще, или требуют модерации, чтобы разблокировать застрявшие таблицы, если кто-то закрыл ее во время работы над ней и т.д...
Ответ 5
1) Это называется блокировкой. Существует два основных типа блокировки при обращении к реляционным базам данных (например, MySQL): блокировка таблицы и блокировка строк. Блокировка таблицы гарантирует, что только один сеанс в момент внесет изменения в таблицу, тогда как блокировка строк гарантирует, что только один сеанс за один раз вносит изменения в определенную строку. Вы можете думать о блокировке строк как более тонком подходе к параллельному доступу, чем блокировка таблицы. Блокировка строк сложнее, но позволяет нескольким параллельным сеансам писать в одну и ту же таблицу (важно, если в вашей базе данных много параллельных записей - блокировка таблицы должна быть хорошей для 10-15 пользователей)
2-3) MySQL заботится о параллельном доступе для вас! Он автоматически реализует блокировку в фоновом режиме. Тип блокировки (строка или таблица) зависит от используемого вами механизма хранения. Например, MyISAM использует блокировку таблиц, а InnoDB использует блокировку строк. Для управления MySQL используется внутренняя таблица. Вы можете запросить статус этой таблицы (и всех блокировок в своей базе данных), проверив переменные Table_locks_immediate
и Table_locks_waited
(он использует ваш вариант номер 2).
Когда вы выдаете инструкцию INSERT или UPDATE, когда другой сеанс использует таблицу (или строку), вызывающее приложение (то есть PHP в этом случае) приостанавливается на несколько миллисекунд, пока другой сеанс не будет написан.
4). Кроме того, MySQL автоматически позаботится о блокировке, но вы можете вручную управлять блокировкой таблиц с помощью команд LOCK TABLES
и UNLOCK TABLES
. Если вы используете блокировку строк с помощью InnoDB, существует множество функций, которые можно использовать для ручного управления одновременным доступом.
См. страницу MySQL Внутренняя блокировка для обзора системы блокировки MySQL и Параллельные вставки для функций блокировки строк InnoDB.
Ответ 6
Как говорили другие, гораздо легче справиться с противоречивым обновлением.
То, что вы предлагаете, называется пезимистической блокировкой. Он назывался thate, потому что слишком вероятно, что два пользователя будут пытаться редактировать одну и ту же запись одновременно.
Это правда?
И это катастрофа, если пользователь должен начать заново, потому что данные, которые они пытались обновить, были изменены кем-то другим.
Затраты на блокировку, вы всегда блокируете пессимистическую схему, поэтому у вас есть накладные расходы, и прежде чем вы начнете смотреть на связанные данные и т.д.
Сделав его надежным, работа с ним никто не может сделать это теперь, потому что sumfin 'пошло не так...
Если бы у меня было что-то, кроме редактирования целого файла, для которого требовалась пессимистическая блокировка, я бы посмотрел на мой дизайн, исходя из того, что он не подходит для цели.