--single-transaction仅对InnoDB表有效,遇MyISAM等非事务表会自动退化为FLUSH TABLES WITH READ LOCK导致锁表;需用SELECT查information_schema确认全库引擎,并监控SHOW PROCESSLIST验证是否真无锁。

--single-transaction 是唯一能真正避免锁表的参数,但只对 InnoDB 表生效;一旦库中存在任意 MyISAM、MEMORY 或 CSV 表,它会自动退化为 FLUSH TABLES WITH READ LOCK,业务立刻卡死。
如何确认 --single-transaction 是否真的生效
别信命令里写了就管用。执行备份时,开另一个终端立刻查:
SHOW PROCESSLIST;
重点看 State 列是否出现 Waiting for global read lock 或 Locked,且 Info 含 FLUSH TABLES WITH READ LOCK —— 有就是已锁表。同时运行:
SELECT table_name, engine FROM information_schema.tables WHERE table_schema = 'your_db';
只要返回结果里有一行 engine 是 MyISAM、MEMORY 或 CSV,--single-transaction 就已失效。
- mysqldump 不会报错,也不会警告,它只是默默切换模式
- 即使只有一张日志表是 MyISAM,整库备份都会被锁
- MySQL 8.0+ 的数据字典表(如
mysql.ibd)不参与此检查,但information_schema和performance_schema表也不走 MVCC,不过它们不影响--single-transaction生效
为什么加了 --single-transaction 还卡在 Waiting for table flush
这不是锁表,是快照建不起来。InnoDB 需要基于当前 innodb_history_list_length 构建一致性视图,若存在长事务(比如未提交超 30 秒),它会一直等那个事务释放 undo log。
- 查活跃事务:
SELECT trx_id, trx_started, trx_state FROM INFORMATION_SCHEMA.INNODB_TRX ORDER BY trx_started LIMIT 5; - trx_started 超过 30 秒的,基本就是卡点;别等它自己结束,协调业务提交或
KILL对应线程 -
innodb_lock_wait_timeout设太低(如默认 50)会导致 mysqldump 被误杀,建议设为600 - 备份窗口内严禁跑大事务:无 LIMIT 的
DELETE、UPDATE、ALTER TABLE
纯 InnoDB 库也得配齐这些参数才安全
--single-transaction 单独用不行,必须搭配 --quick(即 -q),否则大表导出会把整张表缓存进内存,触发 max_allowed_packet 错误或 OOM。
-
--skip-lock-tables必须显式加上,防止脚本或环境变量里残留--lock-tables导致覆盖 - 禁用
--lock-all-tables和--lock-tables:这两个参数和--single-transaction互斥,一加就退化 - 不要用
--lock-tables=false:它不提供任何一致性保障,备份期间跨表更新会导致 A 表旧、B 表新,恢复后逻辑断裂 - 大表导出可主动分片:
mysqldump --where="id BETWEEN 1 AND 100000" db table,但注意--where不支持多表联合导出,需配合--tables
MyISAM 表没法删?那就换方案
如果业务强依赖 MyISAM(比如全文索引老版本实现),硬转 InnoDB 不现实,就得绕开逻辑备份。
- MySQL 8.0+ 可用
LOCK TABLES FOR BACKUP:它只阻塞 DDL 和 MyISAM 写入,InnoDB 读写完全不受影响,锁持时间毫秒级 - 物理层快照(LVM/ZFS/EBS):
FLUSH TABLES WITH READ LOCK→ 打快照 →UNLOCK TABLES,全程锁表时间压到 1 秒内 - Percona XtraBackup:对 InnoDB 真零锁,MyISAM 部分仍需 FTWRL,但它只用于拷贝
.frm和.MYI,耗时极短;务必配--ftwrl-wait-timeout=10 - 切记:所有替代方案都要求提前关闭
autocommit=0的连接,否则事务无法自动开启,快照机制直接失效
最容易被忽略的是“混合引擎”这个硬条件——哪怕只有一张临时表是 MyISAM,--single-transaction 就形同虚设。线上库别靠猜,每次备份前先跑一遍引擎检查,比救急 kill 进程省十倍时间。


















