还原后count(*)结果不对,大概率是事务未提交、连错库或max_allowed_packet截断insert;应先查autocommit状态、当前数据库名及还原日志报错,再用sql精准比对差异。
还原成功但 select count(*) 结果不对,大概率不是“没还原完”,而是事务未提交、连错库、或 max_allowed_packet 截断了大 insert —— 这三类问题占实际案例的 80% 以上。
还原后 COUNT(*) 明显偏少,先查这三件事
别急着重导,花 2 分钟确认以下状态:
- 执行
SELECT @@autocommit;:若返回0,说明所有还原语句都在未提交事务里,新开查询窗口就看不见数据 - 执行
SELECT DATABASE();:确保当前会话默认库是你刚还原的目标库,不是同名但不同实例的旧库 - 检查 Navicat 还原日志末尾有没有类似
Packet too large或MySQL server has gone away的报错——这是max_allowed_packet不够导致 INSERT 被截断的典型信号
用 SQL 直接查差异行,比 Navicat「数据内容对比」更快更准
「数据内容对比」对百万级表容易卡死或 OOM,且依赖主键/唯一索引;直接 SQL 查差异既绕过客户端内存限制,又可精准定位缺失或错乱的记录:
例如比对两张表的主键分布:
SELECT 'missing_in_target' AS why, id FROM source_db.t1 WHERE id NOT IN (SELECT id FROM target_db.t1) LIMIT 100;
再查主键存在但字段值不一致的记录:
SELECT s.id, s.name, t.name FROM source_db.t1 s JOIN target_db.t1 t ON s.id = t.id WHERE s.name != t.name OR (s.name IS NULL) != (t.name IS NULL);
- 务必在
WHERE中显式处理NULL比较,MySQL 中NULL != NULL返回NULL(即 false) - 如果字段含空格或大小写敏感,加
TRIM()和BINARY强制比较:BINARY TRIM(s.name) != BINARY TRIM(t.name) - 时间字段比对前先统一精度:
DATE_FORMAT(s.updated_at, '%Y-%m-%d %H:%i:%s') != DATE_FORMAT(t.updated_at, '%Y-%m-%d %H:%i:%s')
Navicat 还原设置里两个关键开关必须改
默认配置会悄悄破坏还原完整性:
- 取消勾选「遇到错误时继续」:否则一条 INSERT 失败,后续几百条全跳过,你却只看到“还原成功”提示
- 取消勾选「在每个运行中运行多个查询」:该选项会让 Navicat 把大 SQL 拆成并发块执行,极易触发锁冲突或
max_allowed_packet误判 - 还原前手动执行
SET autocommit = 1;,避免依赖脚本末尾的COMMIT;(很多导出文件根本没写)
真正麻烦的不是数据量对不上,而是你不知道哪一行丢了、为什么丢——日志里没报错、Navicat 显示绿色对勾、SHOW TABLES 都在,但某张订单表少了一半记录。这种时候,别信界面提示,直接翻还原日志和查主键缺口。











