mysqldump 加 --master-data 卡住是因为默认执行 FLUSH TABLES WITH READ LOCK,需获取全局 MDL 锁,而长事务或未提交 DML 会阻塞该锁。

mysqldump 加 --master-data 为什么会卡住?
因为 --master-data=1 或 --master-data=2 默认会执行 FLUSH TABLES WITH READ LOCK,这个操作需要获取全局 MDL 锁(Metadata Lock),而只要存在长事务、未提交事务、或正在执行的 DML(比如一个没结束的 UPDATE),锁就拿不到,mysqldump 就会一直等待,直到超时报错 Lock wait timeout exceeded。
常见错误现象:mysqldump 卡在 “Dumping data for table …” 前不动;MySQL 错误日志里出现大量 Waiting for table metadata lock;SHOW PROCESSLIST 中看到状态是 Waiting for table metadata lock 的线程。
-
--master-data=1和--master-data=2行为一致,都会触发 FTWRL,区别只在 binlog 位置是否写进 dump 文件(=2是注释形式,=1是直接执行语句) - 即使加了
--single-transaction,只要用了--master-data,FTWRL 仍会执行——两者不互斥,但--single-transaction无法绕过锁 - 5.7.24+ 和 8.0.1+ 支持
--source-data替代方案,但仅限于复制场景,且仍可能触发锁,不推荐盲目替换
怎么避免 FTWRL 导致的锁等待?
核心思路:不用 FLUSH TABLES WITH READ LOCK,改用轻量级一致性快照 + 手动记录 binlog 位点。前提是引擎必须是 InnoDB,且不能有 MyISAM 表(否则无法规避 FTWRL)。
- 去掉
--master-data,改用--single-transaction --dump-slave=2(MySQL 5.6+)或--source-data=2(8.0.22+),它们会基于当前事务快照输出 binlog 位置,不加全局读锁 - 手动先查位点再 dump:
mysql -e "SHOW MASTER STATUS\G" | grep -E "File|Position"
,记下File和Position,然后用--single-transaction备份,最后把位点信息追加到 dump 文件末尾 - 如果实例有 MyISAM 表,
--single-transaction无效,只能接受 FTWRL;此时建议提前 kill 掉长事务,或选业务低峰期执行
lock_wait_timeout 调大有用吗?
没用。这个参数控制的是单个语句等待 MDL 锁的上限(默认 31536000 秒 ≈ 1 年),不是 mysqldump 自身的超时机制。真正起作用的是客户端连接的 net_read_timeout 和 net_write_timeout,以及 mysqldump 进程自身的信号响应逻辑。
- 调大
innodb_lock_wait_timeout对 FTWRL 无效——它只影响INSERT/UPDATE/DELETE等 DML 的行锁等待,不控制 MDL -
mysqldump没有内置锁等待超时参数,卡住就是卡住,除非外部 kill 或连接断开 - 真正可调的是 MySQL 的
lock_wait_timeout(8.0.1+),但它默认 31536000,几乎等于不限制;设小反而容易让备份失败,不建议动
备份时还有哪些 MDL 相关的坑?
很多人只盯着 --master-data,却忽略了其他隐式触发 MDL 的操作,比如备份过程中有人执行 ALTER TABLE、DROP TABLE,或者连着一个没关闭的事务在查表,都会让 dump 卡在某个表上。
-
mysqldump对每个表单独加 MDL 锁(MDL_SHARED_READ),所以即使不用--master-data,遇到正在被ALTER的表也会等 - 使用
--skip-lock-tables只跳过LOCK TABLES,不影响 MDL;它对一致性无保障,仅适用于只读从库或能容忍数据不一致的场景 - 8.0 中
performance_schema.metadata_locks表可以实时查谁持有/等待哪个表的 MDL,出问题时优先查这个:SELECT * FROM performance_schema.metadata_locks WHERE OBJECT_SCHEMA = 'your_db';
最麻烦的不是锁本身,而是锁的传播性——一个慢查询拖住 FTWRL,FTWRL 又阻塞所有后续 DDL/DML,整个库看起来像“假死”。所以备份前看一眼 INFORMATION_SCHEMA.INNODB_TRX 和 PROCESSLIST 是刚需,不是可选项。










