Сценарий:
Транзакция A начинается...
START TRANSACTION;
UPDATE table_name SET column_name=column_name+1 WHERE id = 1 LIMIT 1;
В то же время начинается транзакция B...
START TRANSACTION;
UPDATE table_name SET column_name=column_name+1 WHERE id = 2 LIMIT 1;
UPDATE table_name SET column_name=column_name-1 WHERE id = 1 LIMIT 1;
COMMIT;
Сейчас транзакция B ожидает строки 1, которая заблокирована в транзакции A.
И транзакция A продолжается...
UPDATE table_name SET column_name=column_name-1 WHERE id = 2 LIMIT 1;
COMMIT;
И теперь у нас есть мертвая блокировка, поэтому обе транзакции ждут друг друга, чтобы разблокировать строку, которую они хотят обновить :'(
Как я спросил в заголовке, как мы можем предотвратить взаимоблокировки в транзакциях РСУБД?
Я думаю, что единственный способ исправить эту ситуацию — откатить транзакцию B и выполнить ее заново. Но как нам узнать, что мы в тупике, и сразу выйти из него, и как мы можем гарантировать, что не попадем в запас и бесконечный цикл (на очень тяжелых веб-приложениях, например).
Если необходимо, я использую MySQL. Но любое решение для других СУБД приветствуется - за помощь другим людям, пришедшим сюда из Google :)