#Что означает неисправность и в каких условиях возникает
Команда ALTER TABLE не завершается и в состоянии соединения видна надпись Waiting for table metadata lock. Случай относится к MySQL/Percona 8.x: изменение структуры обязано дождаться завершения транзакций, которые уже используют таблицу. Нельзя автоматически завершать первую попавшуюся сессию: длительная транзакция может содержать неподтверждённые изменения или операцию импорта. Сначала выясните владельца и согласуйте безопасное завершение.
#Возможные причины: как различить
| Возможная причина | Как узнать | Что делать |
|---|---|---|
| Незавершённая транзакцияВ другой сессии выполнялся SELECT/UPDATE внутри BEGIN и не был вызван COMMIT/ROLLBACK. | В processlist есть длительное Sleep, а запрос ALTER ждёт metadata lock. | Связаться с владельцем транзакции и завершить её осознанно. |
| Долгий запрос или фоновое чтениеОтчёт или резервная копия держит открытую транзакцию во время ALTER. | Найдена сессия с длительным запросом или транзакцией. | Назначить окно обслуживания и дождаться окончания. |
| Очередь новых запросов за ожидающим ALTERПосле начала DDL ожидание может затронуть новые запросы к той же таблице. | В processlist много ожидающих соединений к одной таблице. | Отменить только ожидающий ALTER при риске простоя, затем исследовать блокировку. |
#Пошаговая диагностика и устранение
- Убедитесь, что дело именно в metadata lockВ клиенте MySQL из отдельной администраторской сессии выполните
SHOW FULL PROCESSLIST;и найдите соединение сWaiting for table metadata lock. Запишите идентификатор Id, User, Time и выполняемый ALTER. Если видитеWaiting for row lockилиCopying to tmp table, эта инструкция не подходит: нужна диагностика другого ожидания. - Проверьте, находится ли операция под нагрузкойОткройте журнал развёртывания и определите, какой процесс начал ALTER TABLE, какую таблицу он меняет и сколько времени уже ждёт. Для боевого сайта поставьте на паузу новые изменения схемы в панели развёртывания, а не блокируйте все подключения к базе. Уведомите владельца сервиса о возможной очереди запросов.
- Получите список удерживаемых блокировокЕсли Performance Schema включена, под доступом с правом SELECT для служебной таблицы выполните запрос к
performance_schema.metadata_locks, отфильтровав OBJECT_SCHEMA и OBJECT_NAME по реальной базе и таблице. PENDING означает ожидание, GRANTED — захваченную блокировку; идентификатор OWNER_THREAD_ID сам по себе не равен Id команды KILL, поэтому не применяйте его как номер соединения. - Свяжите блокировку с процессомЧтобы сопоставить владельца с Id подключения, используйте соединение
metadata_locksсperformance_schema.threadsпо THREAD_ID: полеPROCESSLIST_IDпоказывает нужное соединение. Если таблица metadata_locks пуста, проверьте доступность измерений Performance Schema, а затем смотрите SHOW FULL PROCESSLIST; отсутствие строк ещё не означает отсутствие блокировок. - Проверьте незавершённую транзакциюПопросите владельца обнаруженного соединения проверить, есть ли там
START TRANSACTIONбез последующего COMMIT/ROLLBACK, и не выполняет ли оно обработку платежей или заказов. Нельзя выполнять чужой COMMIT удалённо; администратор должен согласовать, следует дождаться операции либо отменить её, поскольку потеря неподтверждённых изменений допустима не всегда. - При простое отмените ожидающий ALTER в своей сессииЕсли запрос ALTER запускали вы и он ещё ждёт блокировку, вернитесь в его окно mysql и нажмите Ctrl+C. Убедитесь отдельным SHOW PROCESSLIST, что ожидающий запрос исчез. Отмена ожидания способна снять очередь новых запросов; но если ALTER уже приступил к изменению таблицы, остановка может быть долгой и требует отдельной оценки.
- Запланируйте безопасное изменение схемыСохраните резервную копию или проверенный способ восстановления структуры, выберите окно низкой нагрузки и исключите транзакции, которые держат соединения открытыми. Проверьте на тестовой копии, поддерживает ли планируемый ALTER нужный алгоритм online DDL; не считайте любой ALTER мгновенным и не добавляйте ALGORITHM=INSTANT без проверки допустимости операции.
- Повторите и измерьте результатПосле согласованного завершения блокирующей операции повторите ALTER сначала в тестовой среде и затем в согласованное окно; наблюдайте за SHOW PROCESSLIST и временем ответа сайта. Если очередь сохраняется, соберите список удерживающих и ожидающих сессий с временем, передайте DBA. Для отката изменения схемы нужен отдельный проверенный план, простой ROLLBACK после успешного DDL обычно не возвращает старую структуру.
- Дополнительная команда по темеSQLКомандаТолько чтение данных мониторинга; добавьте фильтр по имени таблицы в своём редакторе SQL после определения её имени.
SHOW FULL PROCESSLIST;SELECT ml.OBJECT_SCHEMA, ml.OBJECT_NAME, ml.LOCK_STATUS, th.PROCESSLIST_ID, th.PROCESSLIST_USER, th.PROCESSLIST_INFO FROM performance_schema.metadata_locks AS ml LEFT JOIN performance_schema.threads AS th ON th.THREAD_ID = ml.OWNER_THREAD_ID WHERE ml.OBJECT_TYPE='TABLE' AND ml.LOCK_STATUS IN ('PENDING','GRANTED');
#Как проверить исправление и что делать, если оно не помогло
Успешный результат — ALTER больше не стоит в Waiting for table metadata lock, а новые запросы не образуют очередь. Если ожидание повторяется, ищите долгоживущие транзакции и перекрытие с резервным копированием, а не увеличивайте lock_wait_timeout без обоснования.