MyISAM 表备份必须锁表,因其无事务和MVCC机制,无法提供一致性快照;mysqldump的--single-transaction依赖InnoDB的MVCC,对MyISAM静默失效,只能退至FLUSH TABLES WITH READ LOCK保障文件级一致性。

MyISAM 表备份必须锁表,因为它没有事务和 MVCC 机制,无法提供一致性快照。
MyISAM 为什么不能用 --single-transaction
mysqldump 的 --single-transaction 参数依赖 InnoDB 的 MVCC 实现无锁快照,而 MyISAM 完全不支持事务——它没有 undo log、没有行级版本控制、也没有可重复读隔离级别的底层能力。只要库中存在任意一张 MyISAM 表(哪怕只是 mysql.help_topic 这类系统表),--single-transaction 就会静默失效,mysqldump 自动退回到 FLUSH TABLES WITH READ LOCK(FTWRL)流程。
FTWRL 对 MyISAM 是唯一可行的一致性保障
MyISAM 数据文件(.MYD)和索引文件(.MYI)是独立的磁盘文件,写操作直接落盘,不经过缓冲池或事务日志。若备份过程中发生写入:
- 可能只拷贝了更新一半的
.MYD文件,导致数据截断 - 索引文件与数据文件不同步,
REPAIR TABLE都无法恢复 - 备份出来的 SQL 插入语句可能基于损坏的原始状态,恢复后主键冲突或丢失记录
所以 mysqldump 必须通过 FTWRL 强制所有 MyISAM 表关闭、刷脏页、进入只读态,才能保证文件层面的一致性。
常见误操作与后果
以下行为看似合理,实际都会破坏 MyISAM 备份一致性:
- 加了
--skip-lock-tables:备份时 MyISAM 表仍在被写入,导出的 SQL 极大概率报错或数据错乱 - 用
LOCK TABLES t1 READ手动锁部分表:mysqldump 内部仍会尝试 FTWRL,触发死锁或等待超时 - 在主库执行备份:FTWRL 会阻塞所有 DML,且复制线程(SQL Thread)也会卡住,加剧主从延迟
- 混用
--single-transaction和--lock-all-tables:后者优先级更高,直接覆盖前者,锁表行为照旧
能绕过锁表的替代方案
如果业务无法接受 MyISAM 锁表停写,只有三条现实路径:
- 迁移到 InnoDB:执行
ALTER TABLE t ENGINE=InnoDB,确认无外键/全文索引等限制后再启用--single-transaction - 改用物理快照:在 LVM/ZFS/EBS 层打快照,整个 FTWRL 持有时间可压缩到秒级(先
FLUSH TABLES WITH READ LOCK,立刻快照,立刻UNLOCK TABLES) - 切到从库备份:确保该从库
Seconds_Behind_Master = 0或极小,且无长查询阻塞 FTWRL 第一阶段
真正棘手的是混合引擎场景——哪怕只有一张 MyISAM 日志表,整个备份链路就失去无锁能力。这不是参数调优问题,而是存储引擎根本能力的边界。


















