Центр Диагностики & База Системных Ошибок

Решения для Windows Server, Active Directory, 1С, СУБД, Linux, Cisco, MikroTik и IP-телефонии.

⚠️ Важная информация Все материалы, инструкции, команды и скрипты предоставлены исключительно в ознакомительных целях. Их применение может повлиять на работу операционной системы, баз данных и сетевого оборудования. Перед выполнением действий обязательно создайте резервную копию. При отсутствии необходимой квалификации обратитесь к ИТ-специалистам.
MYSQL-ERR-1213 Linux / DevOps

MySQL Ошибка 1213 (40001): Deadlock found when trying to get lock

Обновлено: 21.08.2026  ·  Официальная база знаний

Природа взаимных блокировок (Deadlocks) в движке InnoDB

Взаимная блокировка (Deadlock) возникает, когда две или более параллельные транзакции удерживают эксклюзивные блокировки на часть данных и одновременно пытаются захватить блокировки на данные, уже удерживаемые другой транзакцией, образуя замкнутый циклический граф ожидания (Cycle in Wait-For Graph). Движок InnoDB непрерывно отслеживает такие состояния с помощью встроенного механизма Deadlock Detector. Обнаружив цикл, MySQL мгновенно прерывает одну из транзакций (выбирая транзакцию с наименьшим весом — ту, которая выполнила меньше изменений INSERT/UPDATE/DELETE), выполняет ее автоматический откат (ROLLBACK) и возвращает клиенту ошибку:

«ERROR 1213 (40001): Deadlock found when trying to get lock; try restarting transaction»

Бизнес-риски

Сбой фоновых очередей и пакетных обработок данных, сброс пользовательских сессий оформления заказов, рост задержек в работе базы данных при увеличении числа параллельных потоков.

Сравнение таймаута ожидания (1205) и дедлока (1213)

ПараметрОшибка 1205 (Lock Wait Timeout)Ошибка 1213 (Deadlock Detected)
Время до реакцииОжидание до истечения innodb_lock_wait_timeout (обычно 50 сек).Мгновенная реакция детектора (миллисекунды).
Объем откатаПо умолчанию откатывает только упавший стейтмент.Откатывает всю транзакцию целиком до точки BEGIN.
Стратегия устраненияОптимизация долгих запросов и индексов.Строгая нормализация порядка захвата строк и повторы (Retry logic).

Регламент расследования и устранения взаимных блокировок

Сценарий 1: Включение постоянного логирования дедлоков в журнал MySQL

По умолчанию в выводе SHOW ENGINE INNODB STATUS отображается только один последний дедлок. Включите запись всех инцидентов в error.log:

# 1. Включение логирования на лету без перезапуска СУБД:
SET GLOBAL innodb_print_all_deadlocks = ON;

# 2. Персистентное сохранение в my.cnf:
sudo nano /etc/mysql/mysql.conf.d/mysqld.cnf
[mysqld]
innodb_print_all_deadlocks = 1

# 3. Мониторинг появления дедлоков в реальном времени:
sudo tail -f /var/log/mysql/error.log | grep -A 30 "LATEST DETECTED DEADLOCK"

Сценарий 2: Анализ графа дедлока в SHOW ENGINE INNODB STATUS

Выполните команду в консоли базы данных:

SHOW ENGINE INNODB STATUS\G

В блоке ---LATEST DETECTED DEADLOCK найдите две секции: (1) TRANSACTION и (2) TRANSACTION. Проверьте:

  • Какую блокировку удерживал поток 1 (HOLDS THE LOCK) и какую ожидал (WAITING FOR THIS LOCK TO BE GRANTED).
  • Какую блокировку удерживал поток 2 и какую запрашивал.
  • Какая транзакция была выбрана жертвой (WE ROLL BACK TRANSACTION (1)).

Сценарий 3: Архитектурные паттерны устранения дедлоков

  • Строгий порядок сортировки при обновлении: Если два процесса обновляют строки с ID 5 и 10, оба процесса ОБЯЗАНЫ делать апдейты в порядке возрастания: сначала 5, затем 10.
  • Использование транзакций с уровнем изоляции READ COMMITTED: Устраняет блокировки промежутков (Gap Locks), которые чаще всего вызывают взаимные дедлоки при вставках.
  • Реализация механизма Retry в клиентском коде:
    // Паттерн автоматического перезапуска транзакции при дедлоке (PHP / PDO):
    $maxRetries = 3;
    $retryCount = 0;
    while ($retryCount < $maxRetries) {
        try {
            $pdo->beginTransaction();
            // Выполнение SQL-операций...
            $pdo->commit();
            break;
        } catch (PDOException $e) {
            $pdo->rollBack();
            if ($e->getCode() == '40001' || $e->errorInfo[1] == 1213) {
                $retryCount++;
                usleep(50000 * $retryCount); // Экспоненциальная пауза перед повтором
                continue;
            }
            throw $e;
        }
    }

Типовые ошибки администраторов

  • Отключение встроенного детектора innodb_deadlock_detect: Отключение проверки дедлоков переводит систему в режим ожидания 50-секундных таймаутов, что при высоком трафике полностью замораживает пул потоков.
  • Неявные Gap-блокировки при INSERT ... ON DUPLICATE KEY UPDATE: Данный запрос накладывает жесткие Next-Key блокировки на уникальные индексы, провоцируя частые дедлоки при параллельном исполнении.
База данных регулярно фиксирует дедлоки в часы пиковой нагрузки?
Инженеры ITSTM проведут профилирование транзакционной модели, перестроят логику блокировок и оптимизируют индексы в СУБД.
Практический опыт инженера: При пакетной вставке (Batch INSERT/UPDATE) обязательно сортируйте массив данных по первичному ключу перед отправкой запроса в базу. Это гарантирует одинаковый порядок захвата блокировок всеми воркерами и сводит вероятность дедлоков к нулю.

Частые вопросы (FAQ)

Является ли дедлок признаком программной ошибки в MySQL?

Нет. В реляционных базах с ACID дедлоки являются естественным следствием параллельной работы конкурирующих транзакций. Стандарт SQL требует, чтобы приложение умело перехватывать код 40001 и перезапускать транзакцию.

Почему переход на READ COMMITTED уменьшает число дедлоков?

В режиме READ COMMITTED отключаются предикатные блокировки Gap Locks (интервалов между ключами), что исключает конфликты при параллельных вставках в соседние диапазоны.

Как узнать, какая таблица и строка стали причиной дедлока?

В секции LATEST DETECTED DEADLOCK найдите строки 'hex string of record' и 'table `db`.`table` n_fields' — там указано точное физическое смещение и первичный ключ заблокированной строки.

Влияет ли innodb_lock_wait_timeout на дедлоки?

Нет, детекция дедлоков происходит практически мгновенно, не дожидаясь наступления innodb_lock_wait_timeout.