Mysql, состояние гонки
В базе данных есть запись со статусом false. Я ее достаю, делаю некоторые изменения, после чего я ее обновляю, меняя ее статус на true.
Параллельно запущен код, который может эту запись удалить, если она false.
Как мне сделать блокировку тут?
Думал, использовать транзакцию, но есть проблема - она то заблокирует, но после того как снимет блокировку, удаление пролетит, если оно было инициировано, или я не прав?
Ответы (1 шт):
Все правильно, удаление не сработает, и это правильно.
Эта ситуация нечем не отличается в плане логики от ситуации, когда вы изменили статус на true пять минут назад. В этом случае же delete не должен произойти.
Если вас беспокоит, то что пользователь в момент нажатия на кнопку delete видел, что запись находится в таком состоянии, в котором ее можно удалить, то тут ничего не поделаешь, это фундаментальная проблема в системе с конкурентным доступом. Информация, которую видит пользователь, всегда устаревшая. Самая точная информация о текущем состоянии находится в БД и ее будет видно в момент операции изменения и операция может не пройти.
Приложение должно в этом случае обработать правильно ошибку. Для некоторых операций можно сделать автоматически повтор или слить результат операции (например, если кто-то уже удалил, а тут пользователь тоже удаляет, результат то такой же, так что можно пользователя и не беспокоить). Если автоматически нельзя разрулить, то нужно показать пользователю что-то в духе "пока вы тут думали, кто-то уже поменял эту запись"
Альтернативой является получение объекта в эксклюзивный доступ. Так чтоб пока пользователь его меняет, никто другой не мог его менять, а только читать. Но это нужно реализовывать не транзакциями в БД, т.к. долго держать открытой транзакцию плохо (а тут будет долго, пользователь начал процесс изменений, а потом ушел в отпуск - и так и не закончил, все это время держать транзакцию в БД очень плохо).
Это делается флагом, который меняется в одной транзакции, когда пользователь делает операцию типа "получить экслюзивный доступ к объекту". А после того как пользователь собственно изменил, флаг снимается. Пока флаг установлен, модифицировать нельзя, это значить все операции модификации проверяют, что флаг не установлен.
Так же рекомендую почитать Запрет параллельных запросов, модифицирующих те же данные в БД