mysqldiff可生成库结构差异HTML报告,需网络可达及information_schema SELECT权限;pt-table-sync与pt-table-checksum用于行级校验;schema-spy生成带关系图的交互文档;无损发布须满足ALGORITHM=INSTANT和binlog_format=ROW。
用 mysqldiff 生成库结构差异 HTML 报告
直接跑 mysqldiff 是最轻量、无侵入的方式,它不连目标库执行变更,只比对元数据,输出可读 html。前提是两边 mysql 实例网络可达,且账号有 select 权限(information_schema 和对应库)。
常见错误现象:mysqldiff 报错 Access denied for user,不是因为没给库权限,而是没给 information_schema 的 SELECT;或者报 Unknown table 'xxx' in information_schema,说明账号被限制了 schema 级别访问(比如用了 REQUIRE SSL 但未配置客户端证书)。
- 命令示例:
mysqldiff --server1=user:pass@host1:3306 --server2=user:pass@host2:3306 db1:db2 --changes-for=server2 --format=html > diff.html -
--changes-for=server2表示“以 server1 为基准,生成让 server2 变成 server1 的 SQL”,这个方向不能反,否则 HTML 里“新增表”会变成“删除表” - 输出 HTML 默认不带内联 CSS,浏览器打开可能样式错乱;加
--difftype=sql可先确认 SQL 是否合理,再切回html
用 pt-table-sync + pt-table-checksum 做行级一致性校验(非结构)
结构一致 ≠ 数据一致。如果测试库是生产库某时刻的快照,后续又导入过测试数据,那表结构相同但行数/内容可能已偏移——这时候光看 mysqldiff 会漏掉真实风险。
使用场景:灰度发布前验证分库分表后主从延迟是否导致逻辑不一致;或确认备份恢复后的数据完整性。
-
pt-table-checksum在主库执行,把每张表按 chunk 计算 CRC32,结果写入指定库的checksums表;从库必须能查到这张表(所以得提前建好,并授权) -
pt-table-sync --sync-to-master --replicate=test.checksums会读 checksum 结果,生成修复 SQL,但默认不执行——加--execute才真改数据,务必先加--print看 SQL 内容 - 注意:
pt-table-sync对JSON、TEXT大字段敏感,chunk 太大会超时;建议加--chunk-size=1000控制粒度
用 schema-spy 生成带关系图的交互式文档
单纯对比 DDL 不够直观,尤其涉及外键、索引冗余、字段类型隐式转换时。schema-spy 能把表结构+关联+注释渲染成静态 HTML 站点,适合嵌入内部 Wiki 或发给 QA 查看。
立即学习“前端免费学习笔记(深入)”;
容易踩的坑:Java 版本必须匹配——schema-spy-6.2.0.jar 要求 Java 11+,用 Java 8 会直接抛 UnsupportedClassVersionError;另外它默认不扫描 VIEW,需显式加 -noviews=false 参数。
- 命令示例:
java -jar schema-spy.jar -t mysql -db mydb -s mydb -u user -p pass -host localhost -port 3306 -o ./docs - 生成的
relationships.html里点击表名可跳转到字段详情页,右键导出 PNG 关系图(依赖 Graphviz,需提前装) - 如果表太多,首页加载慢,可加
-hq(high quality)跳过缩略图生成,提速明显
无损发布的两个硬约束条件
结构差异报告只是起点,真正落地无损发布,必须卡住两个技术底线:
- 所有 DDL 必须支持
ALGORITHM=INSTANT(MySQL 8.0.12+)或至少INPLACE;像ADD COLUMN加在中间位置、或修改ENUM值列表,会触发COPY算法,锁表时间不可控 - 生产库必须开启
binlog_format=ROW,否则pt-table-sync无法准确定位不一致的行(STATEMENT 格式下函数、变量等会导致主从解析偏差)
很多人以为生成了 HTML 报告就等于安全,其实关键在 DDL 执行时是否真能瞬时完成——这取决于你用的 MySQL 版本、表引擎、字段类型组合,而不是报告本身。



















