navicat结构对比的“差异行数”≠实际差异行数,因其仅比对ddl元数据,table_rows为innodb采样估算值且不参与比对;刷新连接无效,因该值不随连接更新;真实数据一致性须用数据对比或count(*)等手动校验。
navicat 结构对比显示的差异行数 ≠ 实际差异行数,根本原因不是缓存没刷,而是它压根不比“行数”。结构对比(structure compare)只比表名、字段定义、索引、外键、字符集等 ddl 层信息,table_rows 这种运行时统计值根本不参与比对。你看到的“差异行数”,其实是 navicat 在比对完成后,对「被识别为差异的表对象」做的一次额外估算——它调用的仍是 information_schema.tables.table_rows,而这个值对 innodb 来说就是不准的。
为什么刷新连接/缓存完全无效
重新连接或手动点击“刷新”图标,只会触发 Navicat 重新读取 information_schema.TABLES 中的缓存快照,但:
-
TABLE_ROWS是 MySQL 内部维护的采样估算值,不随连接刷新而更新 - InnoDB 不会实时维护精确行数,即使执行
ANALYZE TABLE,估算误差仍可能达 ±40% - Navicat 的结构对比界面里,“差异行数”列只是把每个差异表的
TABLE_ROWS值简单相加,没有真实扫描数据
真正要查“哪些表实际数据不一致”,得绕开结构对比
结构对比解决不了数据一致性问题。如果你怀疑两个库的同名表内容有出入,必须切换到数据比对(Data Compare)或手写 SQL:
- 用
SELECT COUNT(*) FROM table1和SELECT COUNT(*) FROM table2分别查行数,再比数字 - 查主键分布:例如
SELECT MIN(id), MAX(id), COUNT(*) FROM table1,和另一端对齐,能快速发现删/插倾斜 - 抽样校验:比如
SELECT id, md5(CONCAT_WS('|', col1, col2)) FROM table1 ORDER BY id LIMIT 1000,再和目标库同逻辑结果比哈希 - 避免用
EXCEPT直接全量比——大表会卡死,先确认行数、主键范围、索引命中情况再行动
什么时候 ANALYZE TABLE 才有用
仅当你要优化查询计划,或让 EXPLAIN 显示的 rows 估算更接近实际时才需要它。它对结构对比里的“差异行数”无影响,对数据比对结果也无影响:
-
ANALYZE TABLE更新的是索引统计信息(如cardinality),影响优化器选索引,不影响TABLE_ROWS的底层采样逻辑 - MySQL 8.0+ 中,
innodb_stats_persistent = ON(默认)时,统计信息会落盘,但仍是采样估算 - 执行后立刻看
information_schema.TABLES.TABLE_ROWS,数值可能变,但不代表更准——只是换了批采样页
最易被忽略的一点:Navicat 的「结构对比报告」里如果出现“行数不同”的提示,那基本可以忽略——它不是 bug,是设计如此。你要信的永远只有 COUNT(*) 和主键范围,而不是左侧树形列表里那个灰色小数字。











