Задать вопрос

Как отладить обновление строки, залоченой SELECT FOR UPDATE в MySQL8?

Всем привет. Столкнулся с проблемой блокировки записи в БД. Имею MySQL 8.0.35, уровень изоляции транзакций по-умолчанию. Консольный воркер на PHP 8.2 (Yii2) стартует транзакцию, в которой делает SELECT FOR UPDATE таблички:
start transaction;
select * from Table where <conditions> for update; //Блокируем строчку
... //Какие-то операции на PHP
update Table set `balance`=0 where id=XXX //Обновляем заблокированную строчку по ее id
commit;

Выглядит все довольно просто, но почему-то я все равно ловлю на проде случаи, когда эту же строчку пытается изменить сторонний сервис (у меня нет к нему доступа, я не знаю как он работает) и у него это получается, а после коммита транзакции в моем воркере на PHP записанное внешним сервисом значение затирается.
Пробовал воспроизводить ситуацию локально ручками: делал в транзакции SELECT SLEEP(100) перед ее коммитом и пытался выполнить в консоли UPDATE этой же строки, пока висит SLEEP() - ожидаемо получал отлуп из-за блокировки. Пробовал вставить sleep() на PHP перед вызовом $transaction->commit() и запускал обновление строки вторым PHP скриптом - так же ожидаемо ловил сообщение о заблокированной строке.
Обновление записи воркером происходит внутри ActiveRecord::afterSave() - подозревал, что afterSave() стартует свою вложенную транзакцию, но локальный дебаг показывает, что нет - все выполняется в рамках одной транзакции.
Незнаю, куда еще смотреть, как понять, почему происходит такая перезапись? При каких условиях вообще такое возможно? Буду благодарен за любые подсказки, куда смотреть
  • Вопрос задан
  • 531 просмотр
Подписаться 6 Средний 8 комментариев
Пригласить эксперта
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы