MySQL deadlock: повторить транзакцию с ограниченным backoff
При deadlock InnoDB откатывает одну транзакцию и возвращает ошибку 1213. Повторяйте всю транзакцию с небольшим ограниченным backoff, а не только последний SQL-запрос. ??????? ????????? ?????? ?? ????????? ??????? ? ??????? ???? ?????????? ?? ????? ??????.
Рабочий пример
import random
import time
for attempt in range(4):
try:
with connection.begin():
update_inventory(connection)
insert_order(connection)
break
except DeadlockError:
if attempt == 3:
raise
time.sleep((0.05 * 2**attempt) + random.random() * 0.02)Обёртка connection.begin() должна откатывать транзакцию при исключении. После retry действия снова выполняются целиком, поэтому внешние side effects нужно вынести за транзакцию или сделать идемпотентными.
Частый вопрос
Нужно ли менять порядок UPDATE?
Старайтесь обновлять таблицы и ключи в одном порядке во всех транзакциях. Это снижает вероятность deadlock, хотя retry всё равно полезен для редких конфликтов.