Как предотвратить исключение Deadlock в SELECT FOR UPDATE после обновления? - PullRequest
0 голосов
/ 13 января 2019

У меня есть account таблица с 1 строкой. У меня есть 2 темы, которые делают следующее:

1-ая тема:

begin transaction;
select * from account where balance=0 for update;
UPDATE account SET balance = 10 WHERE balance=0;
// waiting here for several seconds
commit transaction;

2-я тема:

begin transaction;
select * from account where balance=0 for update;
commit transaction;

Поток следующий:
1) 1-й поток начинается и продолжается до строки waiting here for several seconds.
2) 2-й поток запускается и блокируется (логически, поскольку 1-й поток еще не снял пессимистические блокировки).
3) 1-й поток успешно фиксирует транзакцию.
4) 2-й поток получает ошибку: ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction

Почему исключение тупиковой ситуации возникает в таком сценарии, если нет тупиков? Я пробовал этот сценарий со всеми 4 уровнями изоляции транзакций и со всеми уровнями изоляции получена одна и та же ошибка.

1 Ответ

0 голосов
/ 14 января 2019

Проблема была в моей ошибке. Таким образом, приведенный выше код на самом деле должен работать. Моя проблема заключалась в том, что я использовал lock in share mode в первом потоке, а во втором я использовал for update. Я думал, что они одинаковы, но на самом деле это не так. Когда я изменил первый поток на использование for update, они начали работать правильно.

Спасибо Shadow , который дал совет использовать монитор состояния innodb для проверки информации о транзакциях взаимоблокировок (SHOW ENGINE INNODB STATUS;).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...