mysql混合库备份中,innodb支持热备而myisam仅支持温备,需用backup-to-image生成.mbi文件确保原子性,增量备份对myisam无效,恢复时须验证.frm完整性、大小写匹配及sql_mode兼容性。

mysqlbackup 默认就能备份 InnoDB 和 MyISAM 混合库,但必须明确:InnoDB 是热备,MyISAM 是温备(只读),不加干预容易在恢复后发现 MyISAM 表数据不一致。
备份时 MyISAM 表会自动锁表,但锁时机很关键
MyISAM 不支持崩溃安全的并发写入,mysqlbackup 在备份过程中会对所有 MyISAM 表执行 FLUSH TABLES WITH READ LOCK。这个锁不是全程持有,而是分阶段加锁 —— 先锁住所有 MyISAM 表、刷盘、拷贝文件,再释放。问题在于:如果锁期间有长事务或慢查询正在修改 MyISAM 表,FLUSH 会卡住,导致整个备份 hang 住。
实操建议:
- 备份前检查是否有长时间运行的 MyISAM 写操作:
SHOW PROCESSLIST过滤Command = 'Query'且State含Locked或Writing to net - 用
--no-locking强制跳过 MyISAM 锁?不行 —— 这会导致 MyISAM 文件状态不一致,恢复后REPAIR TABLE都救不回来 - 若业务允许,可在低峰期加
--throttle=50降低 I/O 压力,减少锁等待时间
backup-to-image 是混合引擎备份唯一靠谱的输出格式
很多人用 mysqlbackup --backup-dir=/path backup 得到一堆散文件,结果 MyISAM 的 .MYD/.MYI 和 InnoDB 的 .ibd 被分别写在不同子目录下,恢复时顺序错乱、校验缺失,尤其跨服务器传输后极易出错。
必须用 backup-to-image 打包成单个 .mbi 文件,原因很实际:
- InnoDB 的 redo 日志和 MyISAM 的文件快照必须原子打包,否则 apply-log 时找不到对应 MyISAM 文件
-
.mbi内部自带 checksum,能验证 MyISAM 文件是否在传输中损坏(MyISAM 没有页校验机制,全靠文件级完整性) - 恢复命令
mysqlbackup --backup-image=file.mbi copy-back会自动识别并按引擎类型分发处理逻辑
增量备份对 MyISAM 实际无效,别依赖它
mysqlbackup 的增量逻辑完全基于 InnoDB 的 LSN,MyISAM 没有 LSN 概念。当你执行 --incremental-base=history:last_full,它只会比对 InnoDB 表的页变更,MyISAM 文件哪怕被改了十次,增量备份也照旧跳过 —— 下次全量恢复时,你拿到的还是上次全备里的 MyISAM 状态。
这意味着:
- 混合库做增量备份,实质只是“InnoDB 增量 + MyISAM 全量” —— 每次增量备份仍会完整拷贝所有 MyISAM 文件
- 不能用增量来缩短 RTO:MyISAM 部分仍要走完整文件复制流程
- 如果库中 MyISAM 表占比高(比如日志归档表),建议单独用
mysqldump --tab定期导出,不要塞进 MEB 流程
恢复时 MyISAM 表可能报错 Table 'xxx' doesn't exist
这不是备份坏了,而是恢复后 MySQL 没加载 MyISAM 表定义。常见于两种情况:
- 备份时用了
--only-known-file-types,但漏掉了.frm文件(MyISAM 必须有 .frm 才能识别结构) - 恢复目标实例的
sql_mode与原库不一致,导致.frm解析失败(比如原库开了STRICT_TRANS_TABLES,新实例没开) - 最隐蔽的坑:MyISAM 表名含大小写,而目标文件系统是 case-insensitive(如 Windows 或某些 macOS 配置),
.MYD和.frm名字匹配失败
验证方式很简单:恢复后进 mysql,执行 SELECT TABLE_NAME, ENGINE FROM information_schema.TABLES WHERE TABLE_SCHEMA = 'your_db';,看 MyISAM 表是否全在列表里。
.frm 是否完整、文件名大小写是否匹配、sql_mode 是否兼容 —— 这些细节在 .mbi 文件里不报错,但会在恢复后第一句 SELECT 就暴露。











