结构同步前必须确认目标库已存在同名数据库,Navicat不会自动创建;需手动执行CREATE DATABASE IF NOT EXISTS并确保字符集与排序规则一致,否则比对可能失败或误生成大量ALTER语句。
结构同步前必须确认目标库已有对应数据库
navicat 的 结构同步 不会自动创建目标数据库,只操作已存在的库内对象。如果目标库不存在,结构同步 会直接报错或跳过所有表——它不会执行 create database。常见错误是源库叫 prod_db,目标连的是 test 实例但没提前建好同名库,结果比对完显示“无差异”或“0 个对象待同步”,实际是根本没加载到表。
实操建议:
- 先手动在目标 MySQL 实例中执行
CREATE DATABASE IF NOT EXISTS prod_db CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 确保目标库的字符集、排序规则与源库一致,否则
比对字符集和比对排序规则选项会触发大量 ALTER 语句,甚至因不兼容导致失败 - 连接目标库时,Navicat 中选中的“数据库”下拉项必须明确指向该库名,不能留空或选错实例默认库
比对时勾选哪些选项直接影响同步安全性和粒度
Navicat 结构同步界面底部有一长串“比对××”复选框,不是全选就保险,也不是全都不选就省事。比如勾选了 比对外键 但没勾选 比对字符集,可能外键被重建了,字段却仍是 latin1 编码,后续插入中文直接报错;又比如勾选 比对自动递增值,而目标表刚清过数据,同步会把 AUTO_INCREMENT=1 强制写回去,导致下次插入主键冲突。
推荐组合(MySQL 场景):
- 必选:
比对表、比对主键、比对索引、比对字符集、比对排序规则 - 谨慎选:
比对外键(若目标库外键约束已手动禁用,同步时会失败;建议先SET FOREIGN_KEY_CHECKS=0再运行脚本) - 通常不选:
比对触发器、比对事件、比对函数(这类对象常含业务逻辑,不应随结构同步自动覆盖)
生成的部署脚本必须人工核对再执行
点击“运行”后 Navicat 会生成一串 DDL 语句,但这些语句未必都适合线上环境。最典型的是:它默认用 DROP TABLE + CREATE TABLE 替换整张表,而不是 ALTER TABLE 增量修改。对于有数据的生产表,这等于直接删库。
关键检查点:
- 查看脚本开头是否有
SET FOREIGN_KEY_CHECKS=0;和SET SQL_MODE='';——缺失会导致外键或严格模式报错 - 搜索
DROP TABLE,确认是否出现在你不想重建的表上;如有,返回上一步取消该表的同步,改用手动ALTER TABLE - 注意
MODIFY COLUMN和CHANGE COLUMN的区别:前者只改类型,后者可同时改名和类型;Navicat 有时会误用CHANGE导致字段重命名,引发应用层报错 - 大表加索引语句(如
ADD INDEX)是否带ALGORITHM=INPLACE或ALGORITHM=INSTANT——没指定的话,MySQL 5.7+ 默认可能走 COPY 算法,锁表数小时
同步完成后外键名冲突怎么办
MySQL 要求同一库中外键名全局唯一。如果源库多个表用了相同外键名(如都叫 fk_user_id),Navicat 同步时不会自动重命名,直接导入会报错 ERROR 1022 (HY000): Can't write; duplicate key in table。
解决方式只有两种:
- 在源库提前统一规范外键命名,例如用
fk_{table}_{column}_{ref_table}格式,再同步 - 同步失败后,手动编辑部署脚本:把重复的外键名替换成唯一值(如
fk_order_user_id_ref_users),再单独执行该段ALTER TABLE ... ADD CONSTRAINT
这个坑不会在比对阶段暴露,只在执行时报错,而且错误信息不提示具体是哪个外键——得翻脚本逐行找 CONSTRAINT `fk_... 才能定位。











