mysqldiff 比手写 sql 查 schema 更可靠,因其直接解析 information_schema 元数据并全量比对表、索引、外键等细节,避免遗漏默认值、字符集、分区等关键项。

mysqldiff 为什么比手写 SQL 查 schema 更可靠
因为 mysqldiff 是 MySQL Utilities 提供的专用工具,它不依赖视图或临时表模拟,而是直接解析 INFORMATION_SCHEMA 中的元数据,并按对象类型(表、索引、外键、列定义等)逐项比对。手写 SQL 容易漏掉默认值、字符集排序规则、自增起始值、分区定义这些细节,而 mysqldiff 默认全量覆盖。
常见错误现象:mysqldiff 报 “No differences found” 却实际有字段类型差异 —— 很可能是没加 --force 或用了旧版(5.7+ 推荐用 MySQL Shell 的 util.checkForServerUpgrade() 替代,但结构比对仍以 mysqldiff 为主)。
- 必须确保两个数据库的连接账号都有
SELECT权限访问INFORMATION_SCHEMA - 如果库名含下划线或特殊字符,要用反引号包裹,例如:
mysqldiff --server1=user:pass@host1 --server2=user:pass@host2 `db_a`:`db_b` - 默认只比对表结构,不比对存储过程、函数、事件 —— 加
--all才启用全对象比对
如何避免 “Access denied” 或 “Unknown database” 错误
这类报错不是权限配错就是连接参数写崩了。mysqldiff 不走 MySQL client 配置文件(如 ~/.my.cnf),所有连接信息必须显式传入,且格式严格:用户名、密码、主机、端口、socket 要一一对应。
典型错误信息:ERROR: Access denied for user 'u'@'x.x.x.x' (using password: YES) 或 ERROR: Unknown database 'xxx'。
- 密码含特殊字符(如
@、/、:)时,必须 URL 编码后传入,例如pass@123→pass%40123 - 本地 socket 连接要写成
--server1=user:pass@localhost:3306:/var/run/mysqld/mysqld.sock,不能省略端口号或路径 - 远程库名大小写敏感,Linux 下
MyDB和mydb是不同库,mysqldiff不做自动转换
输出结果里哪些差异真该立刻处理
mysqldiff 输出分三类:结构差异(Differences)、缺失对象(Missing)、额外对象(Extra)。真正影响应用行为的是前两类中的关键字段变更。
容易被忽略但后果严重的差异:
-
ENGINE=InnoDBvsENGINE=MyISAM—— 事务、外键、崩溃恢复能力完全不同 -
CHARACTER SET utf8mb4vsutf8—— 后者不支持 emoji 和部分生僻汉字 - 列定义中
NOT NULL和NULL不一致 —— 应用插入空值时可能直接报错 - 主键或唯一索引缺失 —— 导致 ORM 自动生成的 upsert 或 delete 逻辑失效
示例输出片段:def `test`.`t1`.`c1`: col `c1` varchar(255) NOT NULL vs varchar(255) NULL —— 这个 NOT NULL 差异就值得停掉同步先修复。
替代方案:没有 mysqldiff 怎么办
MySQL 8.0.21+ 自带 mysqlpump 可导出 schema 并 diff 文本,但不如 mysqldiff 精准;更轻量的做法是用 mysqldump -d 导出结构再用 diff,但会混入时间戳、AUTO_INCREMENT 值等干扰项。
- 安全做法:先用
mysqldump -d -h host1 -u u -p db1 > db1.sql,再用sed -i '/^-- /d; /^SET /d; s/AUTO_INCREMENT=[0-9]*//g' db1.sql db2.sql清洗 - 注意
mysqldump -d不导外键约束,需额外加--skip-triggers --no-create-info组合才能拿到干净 DDL - 如果只是查单个表,
SHOW CREATE TABLE结果最权威,但没法批量跑 —— 写个 shell 循环 +md5sum对比更快
复杂点在于外键引用顺序、触发器定义里的换行和空格,这些在文本 diff 里极难对齐。真要稳定比对,还是得回到 mysqldiff 或升级到 MySQL Shell 的 util.diffObjects()。











