在 MySQL 5.7 中,元数据锁(MDL, Metadata Lock) 机制用于确保数据一致性,但如果处理不当,可能会导致长时间阻塞,影响数据库的并发性能。
MDL 锁的影响
任何 读取 或 写入 操作都会获取 MDL 锁,以防止表结构在操作过程中发生变更。例如,在 SELECT 查询执行时,不能对表进行 ALTER 操作,否则会出现等待现象。
假设以下事务按顺序执行:
1.事务 A 执行:
SELECT SLEEP(3600), id FROM sbtest1 LIMIT 10;由于 SLEEP(3600) 使查询持续 1 小时,MDL 读锁 也会保持 1 小时。
2.事务 B 试图修改表结构:
ALTER TABLE sbtest1 ADD COLUMN age INT;由于 ALTER TABLE 需要 获取 MDL 写锁,但事务 A 未释放 MDL 读锁,事务 B 只能进入 Waiting for table metadata lock 状态,一直等待事务 A 结束。
3.事务 C 执行普通查询:
SELECT * FROM sbtest1 LIMIT 10;由于事务 B 未能获取 MDL 写锁,事务 C 也会等待事务 B 释放锁,进入 Waiting for table metadata lock 状态,造成 连锁阻塞。
优化方案:调整 lock_wait_timeout
MySQL 提供了 lock_wait_timeout 参数,控制 MDL 锁的等待时间。默认值可能长达 1 年,容易导致长时间阻塞。
建议调整此参数,例如设置为 3~10 秒,让超时的 DDL 语句自动终止,避免影响后续事务:
SET GLOBAL lock_wait_timeout = 5;这样,当事务 B 在 5 秒内无法获取 MDL 锁,会直接报错(ERROR 1205 (HY000): Lock wait timeout exceeded; try restarting transaction)而 不会一直等待,从而防止事务 C 也陷入等待状态,提高数据库的可用性。
















