Почему SELECT ... FOR UPDATE иногда возвращает пустой результат?
Есть PHP/Laravel скрипт который выполняет следующее
"SELECT ... FROM a FOR UPDATE"
"SELECT ... FROM b FOR UPDATE"
Пока скрипт запускается редко - то все ОК.
Но если запустить два и более скриптов одновременно, то иногда один из скриптов иногда возвращает пустое значение во втором SELECTе. Под одновременностью я подразумеваю запуск паралельных процессов с разницей во времени запуска в десятки миллисекунд.
Причем это не ошибка, не деадлок, а именно пустой результат. И данные во время этого эксперимента в БД не меняются.
Интересно, что пустой результат возвращает только один из пачки запущенных процессов, а остальные дают корректный результат. Почему так?
Если убрать FOR UPDATE - то все работает как ожидается. Но мне надо все таки заблокировать выбранные строки для последующей их модификации.
P.S.: Как же так! Я раньше доверял MySQL, а тут какая то плавающая бага! Или я что то делаю не так? Или конструкция FOR UPDATE - не надежная?
Таким образом, при выполнении данного запроса, все затронутые записи в базе данных будут заблокированы до завершения сеанса работы с БД или до момента обновления данных записей. Другой скрипт не сможет выбрать заблокированные записи до тех пор, пока не наступит одно из упомянутых условий
Верно, в этом и идея блокировки через FOR UPDATE.
Но я ожидал что при попытке параллельного доступа к заблокированным строкам я получу подвисание до момента снятия блокировки, как это обычно происходит при блокировках. Ну или хотя бы ошибку.
А вместо этого база данных спокойно возвращает пустой результат, то есть по сути неверные данные. Невозможно понять что случилось, то по запросу реально нет данных, то ли они есть, но селекту мешает какой то паралельный процесс.
Как то у меня теперь подрывается вера в ACID и изоляции транзакций.