--single-transaction 依靠 InnoDB 的 MVCC 实现不锁表备份,通过事务快照保证一致性,但仅对 InnoDB 表生效,遇长事务、DDL 或 MyISAM 表会退化为锁表。

mysqldump --single-transaction 为什么能不锁表
它只对 InnoDB 表生效,靠的是 MVCC(多版本并发控制)机制,在事务开始时拍一个一致性快照,后续读都基于这个快照,不阻塞其他连接的写操作。
常见错误现象:mysqldump 执行时业务写入明显变慢、甚至超时,SHOW PROCESSLIST 看到大量 Waiting for table metadata lock —— 这说明你没加 --single-transaction,或者用了 MyISAM 表。
- 必须确保所有待备份的表都是 InnoDB 引擎,
SHOW CREATE TABLE tbl_name可确认 - 不能和
--lock-tables(默认开启)共用,否则会覆盖掉事务行为,得显式加上--skip-lock-tables - 备份期间新创建的表、DDL 操作(如
ALTER TABLE)仍可能触发元数据锁等待,不是“完全无感”
什么时候 --single-transaction 会失效
它在遇到某些操作时会自动退化为锁表,最典型的是备份过程中有长事务未提交,导致快照无法清理旧版本,mysqldump 会卡住并最终失败。
典型错误信息:ERROR 1205 (HY000) at line XXX: Deadlock found when trying to get lock; try restarting transaction 或直接超时中断。
- 执行前先查长事务:
SELECT * FROM information_schema.INNODB_TRX WHERE TIME_TO_SEC(NOW()) - TIME_TO_SEC(TRX_STARTED) > 60; - DDL 操作(如
ADD COLUMN)在备份中途发起,会阻塞--single-transaction的快照建立 - 混合引擎库中只要有一张 MyISAM 表,整个 dump 就会退回到全局锁表(哪怕加了
--single-transaction)
实际备份命令怎么写才稳妥
不是加个参数就万事大吉,得配合场景调参数。比如备份大库时,默认事务隔离级别可能引发锁等待,要主动指定;同时避免因网络或磁盘问题中断后重试失败。
mysqldump --single-transaction --skip-lock-tables --no-autocommit \ --routines --triggers --events \ -u root -p database_name > backup.sql
-
--no-autocommit防止恢复时每行都提交一次,拖慢导入速度 -
--routines和--triggers默认不导出,漏了会导致恢复后逻辑异常 - 如果库中有
JSON字段或高版本特性,注意mysqldump客户端版本不能低于服务端,否则可能报Unknown column type 'json'
备份后校验一致性容易被忽略的点
加了 --single-transaction 只保证“某一时刻的数据逻辑一致”,不代表备份文件本身完整。网络中断、磁盘满、权限不足都会让 backup.sql 缺几行甚至截断,但命令仍返回 0。
- 务必检查输出文件末尾是否含
-- Dump completed on字样 - 用
grep -c "^INSERT INTO" backup.sql对比预估行数,快速识别是否严重截断 - 如果启用了
binlog,建议备份时加--master-data=2,方便后续按位点恢复,但这会额外加全局读锁(只在 dump 开始瞬间),和--single-transaction不冲突
真正麻烦的是跨引擎混用、长事务没清理、以及把 mysqldump 当万能方案去备份 TB 级数据——这时候该切物理备份了。


















