navicat界面显示的行数不准,因其读取的是information_schema.tables.table_rows估算值,innodb误差可达40%~50%,且不实时更新;可靠校验必须用select count(*)在同步前后分别执行并比对。
别信 navicat 界面右下角那个行数
navicat 同步后显示的“源表 12345 行”根本不是真实值,它读的是 information_schema.tables.table_rows —— 这是 innodb 的估算统计,误差常达 40%~50%,且不随写入实时更新。你刚删了 1000 行,它可能还显示原数字;同步开始时它读了一次这个估算值,结束时你再看目标表的 count(*),自然对不上。
真正能用的只有 SELECT COUNT(*),而且必须在同步前后各执行一次:
- 同步前,在源库手动运行
SELECT COUNT(*) FROM your_table;,记下结果 - 同步过程中,确保源表无写入(停业务 or
FLUSH TABLES WITH READ LOCK;) - 同步完成后,立刻在源库和目标库分别执行
SELECT COUNT(*),直接比数字
查具体哪几行不一致:用 EXISTS + 主键比对
行数一致不代表数据内容一致。比如某字段被截断、字符集转换出错、NULL 和空字符串混淆,COUNT(*) 都发现不了。
最轻量可靠的逐行校验方式是主键驱动的差异查询:
SELECT * FROM table1
WHERE EXISTS (
SELECT 1 FROM table2
WHERE table1.id = table2.id
AND (table1.col1 table2.col1 OR table1.col2 table2.col2 OR table1.col3 IS DISTINCT FROM table2.col3)
);
注意点:
-
IS DISTINCT FROM比!=更安全,能正确处理 NULL 对比(MySQL 8.0.19+ 支持;旧版改用(a IS NULL) != (b IS NULL) OR a != b) - 只比业务关键字段,别全字段列一堆
OR,否则索引失效、查询极慢 - 如果表没主键或唯一键,这种比对不可靠,得先补唯一约束或用
MD5(CONCAT(...))聚合校验(但有哈希碰撞风险)
结构同步后自增 ID 错乱,怎么验证是否已修复?
结构同步默认会把源库的 AUTO_INCREMENT 值强行写到目标库,导致后续插入主键冲突。即使你勾选了「忽略 AUTO_INCREMENT」,也要人工确认是否生效:
- 同步后立即查目标库:
SELECT AUTO_INCREMENT FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='your_db' AND TABLE_NAME='your_table'; - 同时查当前最大 ID:
SELECT MAX(id) FROM your_table; - 二者必须满足:
AUTO_INCREMENT > MAX(id)(通常设为MAX(id) + 1) - 如果没满足,说明同步设置没生效,或你漏点了「高级」里的勾选项
Navicat 的「忽略 AUTO_INCREMENT」开关藏在结构同步 →「选项」→「高级」面板里,默认是勾选状态,不点开「高级」就看不到它。
DDL 层面的索引/字段差异,光看同步预览不够
Navicat 结构同步界面上标着“修改索引”,但不告诉你改了什么。比如 KEY idx_a (col1, col2(10)) 变成 KEY idx_b (col1, col2),它只显示“删除 idx_a,创建 idx_b”,不会提示“前缀长度被去掉”。
必须右键该索引行 →「在 DDL 比较中查看」,才能看到原始定义差异:
- 字段顺序不同、ASC/DESC 显式声明、函数索引写法(
UPPER(email)vsLOWER(email))都会被识别为不一致 - MySQL 8.0 的 invisible index 在 5.7 目标库上无法同步,Navicat 会静默跳过,但不会警告
- 字符集或
COLLATE不同(如utf8mb4_0900_as_csvsutf8mb4_unicode_ci)会导致索引行为变化,Navicat 会标记为需重建——这不是误报,是真实风险
最容易被跳过的动作:每次点开「DDL 比较」看一眼,而不是只扫操作类型图标。











