ALTER TABLE завис в MariaDB: как найти блокировку метаданных

Как отличить ожидание блокировки метаданных от долгого ALTER TABLE, найти держателя и выбрать безопасное действие перед повтором миграции.

Если ALTER TABLE в MariaDB стоит в состоянии Waiting for table metadata lock, он ждёт доступа к структуре таблицы. Сначала найдите соединение, которое удерживает несовместимую блокировку, и выясните, почему его транзакция не завершилась.

Перезапуск базы или повторный запуск миграции не заменяет эту проверку. Ниже — порядок для администратора сайта: подтвердить ожидание, связать блокировку с соединением и выбрать действие без случайного обрыва рабочих операций.

1. Отличите ожидание от долгого изменения таблицы

В отдельном административном соединении выполните:

SELECT VERSION();
SHOW FULL PROCESSLIST;

Найдите запрос миграции по базе и имени таблицы. Зафиксируйте его Id, State и время наблюдения: Waiting for table metadata lock указывает на ожидание блокировки метаданных, а другая стадия может означать уже выполняющуюся работу. Большое значение Time само по себе не доказывает причину зависания.

Метаданные описывают структуру таблицы. Транзакция, использовавшая таблицу, может удерживать их блокировку до своего завершения, даже когда последний запрос уже закончился. Это отличается от deadlock в InnoDB: универсальный повтор транзакции здесь не устраняет держателя. Механизм описан в документации MariaDB.

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

2. Сопоставьте таблицу и владельца блокировки

В MariaDB начиная с 10.5.2 доступна таблица performance_schema.metadata_locks. При включённой Performance Schema и сборе метаданных можно выполнить такой запрос; app_db и orders замените своими именами:

SELECT m.OBJECT_SCHEMA, m.OBJECT_NAME,
       m.LOCK_TYPE, m.LOCK_STATUS,
       t.PROCESSLIST_ID, t.PROCESSLIST_COMMAND,
       t.PROCESSLIST_TIME
FROM performance_schema.metadata_locks AS m
LEFT JOIN performance_schema.threads AS t
  ON t.THREAD_ID = m.OWNER_THREAD_ID
WHERE m.OBJECT_SCHEMA = 'app_db'
  AND m.OBJECT_NAME = 'orders';

PENDING обозначает ожидающую блокировку, GRANTED — выданную. Сопоставьте владельцев с Id из списка процессов. Наличие выданной блокировки на той же таблице ещё не доказывает, что именно она мешает ALTER: учитывайте типы блокировок и текущую операцию соединения.

Пустой результат не исключает проблему: сбор может быть выключен или включён слишком поздно. Отсутствие самой таблицы требует проверки версии и конфигурации. Условия работы и поля приведены в описании metadata_locks.

Если установлен плагин metadata_lock_info, альтернативный источник — information_schema.METADATA_LOCK_INFO. Он показывает владельцев активных блокировок, но не является точной копией Performance Schema. Плагин не установлен по умолчанию; не добавляйте его посреди аварии без согласования с администратором.

3. Проверьте незавершённые транзакции

Для InnoDB сопоставьте соединения с транзакциями через INNODB_TRX:

SELECT trx_mysql_thread_id, trx_started, trx_state
FROM information_schema.INNODB_TRX
ORDER BY trx_started;

Соединение в состоянии Sleep может иметь открытую транзакцию. Например, приложение прочитало таблицу внутри транзакции, а затем ждёт внешний ответ, не выполнив COMMIT или ROLLBACK. Это диагностический пример, а не вывод о вашем сайте: подтверждение ищите в коде и журналах приложения.

Не выбирайте виновника только по возрасту транзакции. Сопоставьте таблицу, Id соединения, владельца приложения и время релиза; INNODB_TRX не охватывает все возможные источники блокировок метаданных. Если одновременно растёт число соединений, отдельно проверьте источник подключений к MariaDB.

4. Выберите, что завершать

  1. Миграцию можно отложить. Согласуйте отмену именно ожидающего ALTER через инструмент запуска миграций. После отмены проверьте, исчез ли запрос и вернулся ли сайт к обычной работе.
  2. Найдена забытая транзакция. Её владелец должен решить, допустимы ли COMMIT или ROLLBACK, и завершить её в исходном соединении. COMMIT из вашей диагностической сессии чужую транзакцию не закроет.
  3. Нужно принудительно разорвать соединение. Передайте решение администратору, указав точный Id и затронутую операцию. Отмена запроса не всегда завершает транзакцию; обрыв соединения может вызвать длительный откат и ошибку у пользователя.

Не завершайте все Sleep-соединения подряд и не запускайте несколько одинаковых ALTER. Если изменение уже выполняется, его отмена может занять время; учитывайте это при выборе между ожиданием и откатом релиза.

5. Ограничьте ожидание следующего запуска

Для согласованного повторного запуска можно задать предел ожидания в самой команде. Пример синтаксиса, а не готовая миграция для рабочей базы:

ALTER TABLE app_db.orders WAIT 5 ADD COLUMN note TEXT;

Здесь пять секунд — выбранный пример предела ожидания блокировки, а не лимит длительности всего изменения. NOWAIT позволяет сразу получить отказ, если блокировку получить нельзя; подробности есть в документации WAIT и NOWAIT.

Заранее проверьте команду на стенде с вашей версией MariaDB, структурой и объёмом таблицы. После ошибки сверьте фактическую схему и состояние миграции перед повтором. Режим online DDL и алгоритм изменения выбирайте отдельно: они не заменяют поиск открытой транзакции.

Как подтвердить восстановление

Проверьте завершение миграции, фактическую структуру таблицы, отсутствие прежнего ожидания и работу затронутого сценария сайта. Главная страница с HTTP 200 не подтверждает, что восстановилась операция, которая обращается к этой таблице.

Web-Puls помогает наблюдать доступность публичного URL во время и после релиза, но не видит внутренние блокировки MariaDB. Если держателя определить не удалось или отмена затрагивает рабочие операции, отправьте заявку на диагностику: укажите публичный адрес, время и часовой пояс, симптом и версию базы. Передавайте только обезличенные фрагменты диагностики, без паролей, данных клиентов и полного текста запросов.

Мониторинг сайтов

Найдите источник исчерпания подключений MariaDB по счётчикам и списку сессий. Разбираем пулы, долгие запросы и безопасную проверку результата.

Проверьте свой сайт прямо сейчас

Введите адрес сайта: Web-Puls покажет HTTP-код, время ответа и базовую диагностику. Для постоянного контроля можно подключить мониторинг.

Нужна помощь с диагностикой ошибки?

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