mysqldump默认锁全库仅在含MyISAM表或启用--lock-tables时触发;纯InnoDB库应使用--single-transaction+--quick规避锁与OOM,禁用--lock-tables=false用于生产备份。

mysqldump 默认会锁全库,但不是所有场景都必须锁
默认情况下,mysqldump 对 InnoDB 表执行 FLUSH TABLES WITH READ LOCK(FTWRL),这会阻塞所有写入,导致业务写操作卡住甚至超时。但这个行为只在以下情况触发:未指定事务型备份参数 + 存在 MyISAM 表 + 或使用了 --lock-tables(默认开启)。纯 InnoDB 库完全可以通过参数绕过全局锁。
-
--single-transaction是首选:它用 MVCC 快照保证一致性,全程不加 FTWRL,也不锁表 - 该参数仅对 InnoDB 有效;若库中混有 MyISAM 表,
mysqldump仍会退回到 FTWRL —— 此时需先确认存储引擎分布:SELECT table_name, engine FROM information_schema.tables WHERE table_schema = 'your_db'; - 不要和
--lock-tables共用,否则后者会覆盖前者效果
--single-transaction 要搭配 --quick 才稳
单靠 --single-transaction 只解决“锁”,不解决“内存爆”。大表导出时,mysqldump 默认缓存整张表结果再输出,容易 OOM 或触发 MySQL 的 max_allowed_packet 报错。
- 务必加上
--quick(等价于-q):让 mysqldump 边查边吐,逐行读取、逐行发送 - 若还遇到 packet too large,同步调大客户端和服务端的
max_allowed_packet,例如:mysqldump --max-allowed-packet=512M ... - 注意:
--quick在 MyISAM 表上无效,所以再次强调——先确认引擎
别乱用 --lock-tables=false
看到“锁”就加 --lock-tables=false 是典型误区。它只是跳过锁表逻辑,但不提供任何一致性保障:备份过程中若发生 DML,导出的 SQL 很可能跨事务不一致(比如 A 表导出旧版,B 表导出新版),恢复后数据逻辑错乱。
- 仅适用于:临时导测试数据、日志表、或明确接受“最终一致”的离线分析场景
- 绝对不可用于生产环境主库全量备份
- 它不能替代
--single-transaction,也不是“轻量版事务”——它根本没事务
备份时真被锁了,怎么快速定位和救急
如果已执行的 dump 卡住,且业务明显写入失败,先别急着 kill,快速判断是否是 dump 自身引发的锁:
- 查锁源:
SHOW PROCESSLIST;找State为Locked或Waiting for table flush的线程,看Info是否含FLUSH TABLES WITH READ LOCK - 查谁在用锁:
SHOW OPEN TABLES WHERE In_use > 0;看哪些表被标记为正在使用 - 如果是 dump 进程自己占着 FTWRL,且你确认可以中断备份,直接
KILL [Id]即可释放锁(注意:kill 后 dump 进程退出,备份文件不完整) - 切记:不要 kill 正在执行长事务的业务线程来“解救”dump——那只会把问题从锁表变成事务回滚风暴
真正容易被忽略的是:哪怕用了 --single-transaction,如果备份期间有 ALTER TABLE、CREATE INDEX 等 DDL,依然会被元数据锁(MDL)阻塞,导致 dump 卡住。这种锁不会出现在 INNODB_TRX 里,得看 performance_schema.metadata_locks —— 但线上一般不建议开这个表,默认关闭。所以,备份窗口内最好禁止 DDL。










