navicat 默认不比对隐式继承的字符集,仅识别显式声明;需关闭“忽略列字符集”等三项compare options才能准确识别差异,且主从比对前须验证gtid或元数据时间戳一致性。

Navicat 默认不比对隐式继承的字段字符集
Navicat 16 对 TEXT、VARCHAR 等字段的字符集(CHARACTER SET)比对,只识别显式写在 CREATE TABLE 语句里的声明。如果表级设了 DEFAULT CHARSET=utf8mb4,但某个 content TEXT 字段没写 CHARACTER SET utf8mb4,Navicat 就认为它“无字符集”,而另一端同名字段显式写了 CHARACTER SET latin1,就会标为差异——哪怕运行时行为完全一致。
验证方法很简单:SHOW CREATE TABLE table_name,看字段定义是否带 CHARACTER SET 子句;没带,就是隐式继承,Navicat 不认。
- 修复方式一:在目标库补全显式声明,比如
ALTER TABLE t MODIFY content TEXT CHARACTER SET utf8mb4; - 修复方式二:导出源库 DDL 时勾选“生成显式字符集”(在 Navicat 导出向导的“高级”页)
- 临时绕过:在 Compare Options 中取消勾选
Ignore column character set(注意:该选项名称在中文版里是“忽略列字符集”)
Compare Options 里必须打开的三个关键开关
即使你确认字段有显式字符集,Navicat 仍可能跳过比对,因为默认启用了多项“忽略”选项。真正要让字段编码差异浮现出来,这三个选项必须同时关闭:
-
Ignore TEXT/BLOB column attributes:不关它,TEXT字段的CHARACTER SET、COLLATE、NULL属性全被跳过 -
Ignore column character set:关掉才能启用字段级字符集比对 -
Ignore column collation:排序规则(COLLATE)和字符集是绑定判断的,不关它,utf8mb4_0900_as_cs和utf8mb4_unicode_ci的差异不会单独标出,而是笼统归为“结构不一致”
这些选项都在结构同步窗口 → 右下角 Options → Compare Options 里。改完必须点 OK 再点 Compare,中途修改无效。
COLLATE 差异被误报的常见诱因
Navicat 把 COLLATE 标红,不一定代表运行时有问题。常见干扰项包括:
- 源字段未显式声明
COLLATE(靠表级继承),目标字段显式写了COLLATE utf8mb4_0900_as_cs—— Navicat 视为不同,但实际行为可能完全一致 - DDL 中空格/换行差异:比如
COLLATE utf8mb4_unicode_civsCOLLATE utf8mb4_unicode_ci(末尾多一个空格),Navicat 默认做完整字符串比对,会触发误报 - 导出再导入后自动降级:源库 MySQL 8.0 导出的
utf8mb4_0900_as_cs,在目标库 MySQL 5.7 上执行时静默降为utf8mb4_general_ci,Navicat 比对的是“原始 DDL”和“执行后实际值”,自然不一致
真正要关注的是 _cs(大小写敏感)、_bin(二进制)这类影响查询逻辑的排序规则变更;纯 _ci 类型之间互换,多数情况无需处理。
主从库比对前必须确认 GTID 或元数据时间戳
如果你在比对主库和从库,发现字段字符集“莫名不同”,大概率不是 Navicat 的问题,而是从库还没应用完 DDL。Navicat 执行的是普通 SHOW CREATE TABLE,它读到的是 SQL 线程当前已应用的快照。
别信 Seconds_Behind_Master = 0,得验证真实一致性:
- 在从库执行
SELECT @@gtid_executed,主库也执行,用GTID_SUBSET('从库gtid', '主库gtid')返回1才算追平 - 或直接查元数据时间戳:
SELECT UPDATE_TIME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='db' AND TABLE_NAME='t',主从结果必须严格一致
结构比对这件事,工具只是放大镜;它没法区分“真差异”和“延迟快照”。这点最容易被忽略,却直接决定后续所有同步动作是否可信。











