MySQL deadlock: повторить транзакцию с ограниченным backoff

Категория: Postgresql · Язык: Python · Обновлено:

При deadlock InnoDB откатывает одну транзакцию и возвращает ошибку 1213. Повторяйте всю транзакцию с небольшим ограниченным backoff, а не только последний SQL-запрос. ??????? ????????? ?????? ?? ????????? ??????? ? ??????? ???? ?????????? ?? ????? ??????.

Рабочий пример

Python
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 всё равно полезен для редких конфликтов.