真正持锁的是安静挂着的sleep线程而非waiting线程;需通过performance_schema.metadata_locks查lock_status='granted'对应的processlist_id,并结合innodb_trx确认其为长时间未提交事务。

查谁在持锁,别看“Waiting”那行
显示 Waiting for table metadata lock 的线程只是受害者,不是加锁者。真正要找的是那个安静挂着、Command = 'Sleep'、Time > 300、Info = NULL 的连接——它大概率开了事务但没提交,从 BEGIN 起就一直拿着 MDL_SHARED_READ 锁不放。
必须用 performance_schema.metadata_locks 定位:
- 先确认开关已开:SELECT * FROM performance_schema.setup_instruments WHERE NAME = 'wait/lock/metadata/sql/mdl';,确保 ENABLED 和 TIMED 都是 YES
- 再查锁归属:SELECT OBJECT_SCHEMA, OBJECT_NAME, LOCK_TYPE, LOCK_STATUS, PROCESSLIST_ID FROM performance_schema.metadata_locks m JOIN performance_schema.threads t ON m.OWNER_THREAD_ID = t.THREAD_ID WHERE OBJECT_SCHEMA = 'your_db' AND OBJECT_NAME = 'your_table' AND LOCK_STATUS = 'GRANTED';
- 只关注 LOCK_STATUS = 'GRANTED' 的结果,对应 PROCESSLIST_ID 就是真正在 hold 锁的线程 ID
KILL 前先试 KILL QUERY,避免回滚风暴
拿到持锁线程 ID 后,别直接 KILL [id]。先执行 KILL QUERY [id],只终止当前语句,保留连接和事务上下文。如果它卡在空事务里(TRX_QUERY 为空),KILL QUERY 通常无效,再考虑 KILL [id]。
验证是否真在持锁:
- 查 information_schema.INNODB_TRX:SELECT * FROM information_schema.INNODB_TRX WHERE trx_mysql_thread_id = [id] AND trx_state = 'RUNNING';
- 如果返回结果且 trx_started 时间远超业务预期(比如 >60 秒),基本可确认是悬挂事务
- 注意:SHOW OPEN TABLES WHERE In_use > 0 对 MDL 锁完全无效,别浪费时间
ALGORITHM=INPLACE 不等于不锁,得看操作类型
加 ALGORITHM=INPLACE, LOCK=NONE 不是万能解药,MySQL 会严格校验是否支持,不满足就报错,不会静默降级。
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
-
ADD COLUMN在末尾添加、无NOT NULL DEFAULT:5.6+ 支持 inplace,但仍有短暂排他 MDL 期 -
MODIFY COLUMN改长度或字符集(如VARCHAR(255) → VARCHAR(1024)):5.7 必重建;8.0.12+ 仅当长度头不变、字符集不变、无存储格式升级时才可能 inplace -
ADD INDEX:一般支持LOCK=NONE,但字段没走索引扫描、含BLOB或建唯一索引时可能降级
执行前务必用 EXPLAIN FORMAT=JSON 看执行计划里的 "alter_algorithm": "inplace" 和 "supports_inplace": true 是否同时为 true
生产环境优先用 pt-online-schema-change
它不碰原表 DDL,而是新建影子表 + 触发器同步 + 分块拷贝 + 原子切换,彻底绕开 MDL 锁瓶颈。但有硬性前提:
- 原表必须有主键或唯一非空索引,否则增量同步不可靠
- 原表不能已有触发器,否则冲突
- 执行前加
--print和--dry-run,重点核对生成的RENAME TABLE语句顺序和库名是否正确 - 磁盘空间至少预留原表大小 × 1.5,触发器写入和拷贝过程会产生额外日志与临时文件
- 禁止在从库单独运行再切主从——
pt-osc不复制 DDL,会导致主从结构不一致
最常被忽略的一点:业务层配合。哪怕用了 pt-osc,如果应用端持续开启长事务或连接泄漏,下次 DDL 还会卡在别的地方。锁问题从来不只是数据库的事。










