--single-transaction 能避开全局锁,因为它不依赖 ftwrl,而是利用 innodb 的 mvcc 机制在备份开始时创建 repeatable read 事务快照,后续查询均基于该一致性视图,无需加锁。

MySQL 全局锁备份会让业务完全停写,但用 --single-transaction 可以在 InnoDB 表上实现几乎无感的热备,前提是事务隔离级别为 REPEATABLE READ 且备份期间没有长事务阻塞快照创建。
为什么 --single-transaction 能避开全局锁?
它不依赖 FLUSH TABLES WITH READ LOCK(即 FTWRL),而是利用 InnoDB 的 MVCC 机制,在备份开始时发起一个一致性快照读。这个快照基于当前活跃事务 ID 列表,后续所有 SELECT 都从该时间点的版本链读取数据,无需加表级或行级写锁。
注意:该参数仅对 InnoDB 表生效;MyISAM 表仍会触发 FTWRL,导致锁表。
- 必须确保数据库默认引擎是 InnoDB,或显式只备份 InnoDB 表
- 备份开始前,不能有运行超过数秒的未提交事务——否则
mysqldump会卡在Waiting for table flush状态 - 执行时会自动设置
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ,若客户端显式改过隔离级别,可能被覆盖
--single-transaction 备份失败的典型报错和应对
常见错误信息:mysqldump: Got error: 1205: Deadlock found when trying to get lock 或长时间卡在 Starting transaction。
这通常不是死锁本身,而是备份进程在等待某个长事务释放 undo log 或 purge 线程资源。真实瓶颈往往藏在事务生命周期里。
- 查出干扰事务:
SELECT trx_id, trx_started, trx_state, trx_mysql_thread_id FROM information_schema.INNODB_TRX ORDER BY trx_started LIMIT 5; - 重点看
trx_started时间戳,超过 30 秒的事务建议人工干预(KILL或协调业务提交/回滚) - 避免在备份窗口内执行
ALTER TABLE、大范围UPDATE或未加LIMIT的DELETE
和 --lock-all-tables / --lock-tables 的关键区别
这三个参数控制的是锁粒度与持续时间,直接影响业务可用性:
-
--single-transaction:仅在备份启动瞬间做一次快照,之后全程无锁,适合 OLTP 主库 -
--lock-tables:对每个表依次加READ LOCAL锁,备份期间该表禁止写入,但不同表可并发锁,总锁时长 = 所有表锁时间之和 -
--lock-all-tables:等价于 FTWRL,全库只读,业务写操作全部阻塞,直到备份结束
如果误把 --single-transaction 和 --lock-all-tables 同时使用,mysqldump 会忽略前者并强制走全局锁——这种组合毫无意义,且容易被配置脚本悄悄混入。
生产环境必须检查的三项配置
即使加了 --single-transaction,以下三项配置不到位,热备照样变冷备:
-
innodb_lock_wait_timeout建议设为120(而非默认 50),避免快照初始化阶段因锁等待超时失败 -
max_allowed_packet必须大于单行最大记录长度 × 并发 dump 线程数,否则遇到大 BLOB 字段直接中断 - 备份用户需具备
RELOAD权限(用于RESET MASTER类操作,部分版本要求)、LOCK TABLES(即使不用锁,mysqldump启动时仍会尝试检查)、以及目标库的SELECT权限
真正麻烦的从来不是参数怎么写,而是那个没被监控到的、跑了 7 分钟还没提交的订单补偿事务——它会让所有 --single-transaction 备份在第一秒就卡死。











