--single-transaction能避免锁表,因为它不触发flush tables with read lock,而是通过start transaction with consistent snapshot利用innodb的mvcc生成一致性快照,后续select均从此快照读取,全程无表级或行级写锁,但仅对innodb有效,且需repeatable read隔离级、无长事务、不与--lock-all-tables混用。

用 --single-transaction 是最直接有效的解法,但只对 InnoDB 表生效,且必须避开长事务;否则备份会卡在 Waiting for table flush,业务照样停摆。
为什么 --single-transaction 能避免锁表
它不触发 FLUSH TABLES WITH READ LOCK(FTWRL),而是在备份开始时执行 START TRANSACTION WITH CONSISTENT SNAPSHOT,利用 InnoDB 的 MVCC 机制生成一个时间点快照。后续所有 SELECT 都从该快照读取,不加任何表级或行级写锁。
关键前提是:innodb_lock_wait_timeout 建议设为 120,且事务隔离级别必须是 REPEATABLE READ(mysqldump 会自动设置,但如果客户端显式改过,可能被覆盖)。
常见误操作:
- 混用
--single-transaction和--lock-all-tables:后者会强制覆盖前者,退化为全局锁 - 备份前存在运行超 30 秒的未提交事务:
mysqldump会无限等待其释放 undo log,表现为卡住 - 库中混有 MyISAM 表:该参数对 MyISAM 无效,仍会触发 FTWRL
备份卡在 Waiting for table flush 怎么办
这不是网络或磁盘问题,而是备份进程在等某个长事务结束。此时查 INFORMATION_SCHEMA.INNODB_TRX,重点关注 trx_started 字段:
- 超过 30 秒的事务建议人工干预:协调业务提交或回滚,或
KILL对应线程 - 避免在备份窗口内执行
ALTER TABLE、大范围UPDATE或无LIMIT的DELETE - 加
--quick参数防止内存溢出,尤其对大表:它让mysqldump每次只取一行,而不是缓存整张表
MyISAM 表或混合引擎怎么办
只要库中存在 MyISAM 表,--single-transaction 就会失效。这时必须换策略:
- 优先迁表:
ALTER TABLE t ENGINE=InnoDB,确认innodb_file_per_table = ON - MySQL 8.0+ 可用原生命令替代 FTWRL:
LOCK TABLES FOR BACKUP(仅阻塞 DDL 和 MyISAM 写入,InnoDB 读写照常) - 物理层兜底:用 LVM/ZFS/EBS 快照,
FLUSH TABLES WITH READ LOCK只需毫秒级持锁,之后所有拷贝都在快照里进行 - Percona XtraBackup:对 InnoDB 无锁,但遇到 MyISAM 仍需 FTWRL;务必关闭
innodb_lock_wait_timeout短超时,防误杀备份线程
容易被忽略的三个硬性条件
即使写了 --single-transaction,以下三点任一不满足,热备就变冷备:
- 数据库默认引擎不是 InnoDB,或备份命令没限定表名,导致 mysqldump 自动 fallback 到 FTWRL
- 备份脚本里隐式设置了
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED,覆盖了--single-transaction所需的REPEATABLE READ - 备份目标实例启用了
read_only=ON,而备份用户没被授予BACKUP_ADMIN权限(MySQL 8.0+)或RELOAD权限(旧版),导致权限不足触发降级锁











