根本原因是Navicat默认导出SQL脚本时显式指定id值,若目标表已有数据且新id已存在或小于当前AUTO_INCREMENT值,就会触发主键冲突错误。
还原时自增主键冲突的根本原因
navicat 默认导出的 sql 脚本包含 insert into table (id, name) values (1, 'a') 这类显式指定 id 的语句。若目标表已有数据,且新插入的 id 值已存在或小于当前 auto_increment 值,mysql 就会报错:error 1062: duplicate entry '1' for key 'primary' 或触发自增偏移异常。
导出脚本前必须关闭“导出主键值”选项
这是最直接有效的预防方式——让 Navicat 生成不带 id 列的 INSERT 语句,交由 MySQL 自动分配新 ID。
- 在 Navicat 中右键数据库/表 → “转储SQL文件” → “结构和数据”
- 点击 “高级” 选项卡
- 取消勾选
Export primary key values(中文版显示为“导出主键值”) - 确保
Insert statements模式启用(默认开启)
导出后你会看到类似 INSERT INTO user (name, email) VALUES ('a', 'a@b.c') ——id 列完全不在字段列表中,MySQL 会自动补全并递增。
如果已导出含 ID 的脚本,临时修复方法
手动删改效率低且易出错,推荐用文本工具批量处理(如 VS Code、Notepad++),但要注意语法边界:
- 查找模式(正则):
INSERT INTO `(\w+)` \(([^)]*),\s*`id`([^)]*)\) VALUES \(([^)]*),\s*(?:\d+|NULL)([^)]*)\); - 替换为:
INSERT INTO `$1` ($2$3) VALUES ($4$5); - 更稳妥的做法是先执行
SET FOREIGN_KEY_CHECKS = 0;和SET SQL_MODE = 'NO_AUTO_VALUE_ON_ZERO';,再用TRUNCATE TABLE清空目标表(慎用,会重置自增值)
注意:若原表有外键依赖,TRUNCATE 可能失败,此时需先 DELETE FROM + ALTER TABLE ... AUTO_INCREMENT = N 手动重设起点。
还原后检查自增值是否连续不是必须的
MySQL 的 AUTO_INCREMENT 只保证唯一性和单调递增,不保证连续。跳号(如 1→2→4)是正常现象,尤其在事务回滚、批量插入失败或手动指定 ID 后发生。只要新插入数据不再冲突,就不需要干预。
真正要盯住的是:还原后首次插入是否成功、应用层是否收到重复主键错误、以及 SHOW CREATE TABLE 中的 AUTO_INCREMENT 值是否合理(比如远小于当前最大 ID,可能引发后续冲突)。











