用mysqldump生成可比对备份需加--skip-extended-insert、--order-by-primary、--skip-comments、--no-tablespaces四参数;线上数据须用mysql -n -s -r直连导出tsv,再转为同格式insert后diff比对。

用 mysqldump 生成可比对的备份快照
直接拿原始 mysqldump 输出做 diff 很容易失败——默认会带时间戳、随机排序、表结构顺序不一致。必须统一输出规范,否则脚本一跑就误报。
关键操作是加这四个参数:--skip-extended-insert(每行一条 INSERT)、--order-by-primary(按主键排序)、--skip-comments(去掉注释)、--no-tablespaces(避免 .ibd 路径干扰)。
示例命令:
mysqldump -h127.0.0.1 -uuser -ppass --skip-extended-insert --order-by-primary --skip-comments --no-tablespaces db_name table_name > backup.sql
- 别漏掉
--order-by-primary:没它,同一张表两次 dump 的 INSERT 行序可能不同,diff 100% 不通过 - 如果表没主键,
--order-by-primary会静默失效,得改用--where="1=1 ORDER BY col1,col2"手动指定排序字段 -
mysqldump默认不 dump 视图定义,要校验视图需额外加--no-create-info --skip-triggers单独导出
用 mysql 命令直连查线上数据并标准化输出
不能依赖应用层取数——字段类型隐式转换、NULL 处理、时区、字符集都可能让结果和 dump 不一致。必须用 MySQL 客户端直连,且强制统一格式。
核心是用 mysql -N -s -r 三个开关:-N 去掉列名、-s 简洁模式(tab 分隔)、-r 原始输出(不转义特殊字符)。
示例查询:
mysql -h127.0.0.1 -uuser -ppass -N -s -r -e "SELECT id, name, created_at FROM db_name.table_name ORDER BY id" > live.tsv
- ORDER BY 必须显式写,且字段要和 dump 中 INSERT 的列顺序完全一致
- 日期字段如
created_at在 dump 里是字符串形式('2024-01-01 12:00:00'),线上查出来也得保持同样格式,避免用NOW()或函数包装 - 字符集不一致会导致中文乱码对比失败,连接时加
--default-character-set=utf8mb4
用 diff 或 md5sum 做最终比对
文本级比对最稳,但要注意中间产物是否真正可比。别一上来就 diff backup.sql live.sql——live.sql 是 INSERT 语句,而你从线上查的是 TSV,格式根本不匹配。
正确路径只有一条:把线上数据也转成和 dump 一样的 INSERT 格式,再比对。
简单做法是用 Python 脚本读 live.tsv,拼出标准 INSERT(注意 NULL、引号、转义),输出到 live_inserts.sql,再 diff backup.sql live_inserts.sql。
- 别用
md5sum backup.sql和md5sum live.sql直接比——live.sql 是 SELECT 结果,backup.sql 是 INSERT 语句,毫无可比性 - 大表慎用全量 INSERT 拼接:内存吃紧或超长行被截断,建议分批次处理,按主键范围切片
- 空表容易漏判:dump 出来是
INSERT INTO ... VALUES ();,而线上查可能返回空文件,diff 会报“文件长度不同”,得提前检查空表情况
自动化脚本里最容易被忽略的三个点
不是写个 for 循环 dump 所有表就叫自动化了。真实环境里,下面三点不处理,脚本跑三天后突然挂掉,没人知道为啥。
-
mysqldump遇到锁表会卡住,默认超时是 0(无限等待),必须加--lock-wait-timeout=30并捕获ERROR 1205 (HY000): Deadlock found - 备份前没校验磁盘空间,
df -h /backup少于 2GB 就该中止,否则 dump 写一半失败,留下残缺文件 - 线上库开了
sql_mode=STRICT_TRANS_TABLES,但备份机没开,INSERT 里非法日期(如 '0000-00-00')在备份机里能插入,在线上直接报错——校验前先确认两边 sql_mode 一致
校验这事,90% 的坑不在逻辑,而在环境一致性。表结构一样、数据一样、但 sql_mode、时区、字符集差一点,结果就对不上。











