--single-transaction对TB级大表实际失效,因其事务超时、undo log压力大、易被DDL中断;应改用XtraBackup热备或分表+限速导出。

不能靠单次 mysqldump 命令完成 TB 级大表的“不锁库”备份 —— 它不是参数调得够细就能绕过的限制,而是设计边界问题。
为什么 --single-transaction 对 TB 表实际失效
参数本身没错,但 MySQL 的事务快照机制在超大表上会暴露两个硬伤:
- 事务持续时间过长,触发
innodb_lock_wait_timeout(默认 50 秒),导致 mysqldump 中途报错退出,日志里常见Lock wait timeout exceeded - 即使没超时,
SELECT * FROM huge_table在 MVCC 下仍需维护大量 undo log 和一致性视图,主库内存和 IO 压力陡增,业务写入延迟明显升高,本质是“不显式锁表,但拖垮服务” -
--single-transaction要求整个事务期间无 DDL;而 TB 表常伴随在线 DDL(如加列、改字段),一旦发生就会隐式提交,直接中断快照,报错Cannot execute statement in a READ ONLY transaction
真正可行的替代路径:跳过 mysqldump 主流程
对单张 TB 表,逻辑导出已不是首选。必须转向存储层直取,且不依赖 SQL 解析:
- 用
Percona XtraBackup 8.0+:唯一支持 InnoDB TB 表热备的成熟方案,备份时只读取 ibd 文件 + redo 日志,完全绕过 SQL 层,CPU/内存开销可控 - 务必启用限速:
--throttle=100(每秒 IO 操作数)或--rate=20M(每秒读取字节数),否则可能打爆磁盘带宽 - 备份前确认
innodb_file_per_table=ON,否则 XtraBackup 无法单独处理单表,只能全库备份 - 不要试图用
mysqldump --where分页导出——WHERE 条件若无合适索引,全表扫描照样卡死;有索引也难保分页间隙数据不丢失
如果非要用 mysqldump(例如合规要求纯 SQL 备份)
只能接受“分片 + 降级保障”,而非“单命令无锁”:
- 先拆表:用
ALTER TABLE huge_table REMOVE PARTITIONING(若已是分区表)或按业务字段(如created_at)手动切为多个 50GB 左右的子表,再逐个mysqldump --single-transaction --quick --skip-triggers --skip-routines - 客户端和服务端同步调大:
--max-allowed-packet=2G+ MySQL 配置中max_allowed_packet=2G,否则导到一半报Packets larger than max_allowed_packet - 禁用所有非必要开销:
--skip-autocommit --no-tablespaces --skip-extended-insert(后者避免单行 INSERT 占满内存) - 绝对不要加
--opt(它等价于--add-drop-table --add-locks --create-options...,其中--add-locks会插入LOCK TABLES,直接锁库)
最容易被忽略的致命点
没人检查备份过程中的 SHOW PROCESSLIST —— 你看到 mysqldump 进程状态是 Sending data,但它背后可能正持有 MDL(metadata lock) 阻塞后续 DDL,而这个锁不会出现在 INFORMATION_SCHEMA.INNODB_TRX 里,常规监控根本捕获不到。TB 表备份动辄数小时,这段时间内任何 ALTER TABLE 请求都会排队挂起,最终拖垮整个集群的 DDL 队列。


















