mysqldump --single-transaction仅对innodb表有效,依赖repeatable read隔离级别、全库innodb引擎且无ddl操作;遇myisam表或alter等ddl会失效,需配合--skip-lock-tables和--master-data=2并严格管控环境。

mysqldump --single-transaction 能在不停机前提下实现 InnoDB 表的一致性备份,但**不是所有场景都安全可用**——它只对 InnoDB 有效,且依赖隔离级别、引擎统一性和 DDL 管控。
为什么 --single-transaction 不等于“完全无锁”
这个参数本质是让 mysqldump 在开始导出前执行 START TRANSACTION WITH CONSISTENT SNAPSHOT,依靠 InnoDB 的 MVCC 提供时间点一致视图。但它不锁表,也不阻塞写入,所以看起来“热”。可实际有隐藏开销:
- 若备份期间存在长事务未提交,
mysqldump会等待其结束才能建立快照,导致备份卡住甚至超时 - 默认行为仍会尝试对非事务表(如 MyISAM)执行
FLUSH TABLES WITH READ LOCK,造成全局读锁——这和“不停机”目标直接冲突 - 必须显式加
--skip-lock-tables才能跳过这一步,但前提是确认库中**没有非事务引擎表**
如何验证并确保引擎全是 InnoDB
别凭经验猜测,直接查 information_schema:
SELECT table_name, engine FROM information_schema.tables WHERE table_schema = 'your_db_name';
如果结果里出现 MyISAM、MEMORY 或 ARCHIVE,--single-transaction 就不可靠。此时有两个选择:
- 改用
--lock-all-tables(全局读锁,短暂阻塞写入,但保证任意引擎组合下一致性) - 先迁移非 InnoDB 表:
ALTER TABLE tbl_name ENGINE=InnoDB;,再启用--single-transaction
DDL 操作会让一致性快照彻底失效
--single-transaction 只隔离 DML(INSERT/UPDATE/DELETE),对 DDL(DROP TABLE、ALTER TABLE、RENAME TABLE)完全无防护。典型风险:
- 备份中途
DROP TABLE users→ dump 文件里可能有CREATE TABLE users语句,但没对应数据,恢复时报错 -
RENAME TABLE orders TO orders_old→mysqldump可能读到旧表名,又读不到新表结构,导出中断或内容错乱
最稳妥做法:把备份窗口设为业务低峰期,并**明确禁止所有 DDL 操作**。若无法规避,应改用 Percona XtraBackup(它在文件系统层拷贝,配合 redo log 回放,对 DDL 更鲁棒)。
真正“不停机”的底线要求
即使满足全 InnoDB + 无 DDL + --skip-lock-tables,仍需注意两个易被忽略的点:
-
autocommit=1必须开启。如果连接里手动开了事务且未提交,--single-transaction会失败或行为异常 - 备份命令里务必包含
--master-data=2(记录 binlog 位点),否则无法用于主从搭建或基于时间点恢复(PITR)
最终推荐命令模板:
mysqldump -u root -p --single-transaction --skip-lock-tables --master-data=2 --routines --triggers --databases your_db > backup_$(date +%F).sql
记住:只要库中混了非事务表,或备份时有人执行了 ALTER,这个命令就不再“一致”——它只对严格受控的 InnoDB 场景有效。











