Navicat的数据传输功能是唯一能同时处理跨服务器、表结构+数据及外键依赖的可靠方式;需确保源库有SELECT权限、目标库有CREATE/INSERT权限,提前建好同字符集的目标数据库,并严格按“左源右目标”操作,大表迁移须关闭事务、开启批量插入,字段类型不兼容时需手动映射。
直接用 navicat 的 数据传输 功能就行,这是唯一能同时处理跨服务器、表结构 + 数据、外键依赖的可靠方式。其他方法要么不跨服务器(如 create table like),要么只迁数据(如 csv 导入),要么要手动拼 sql(易出错且难审计)。
确认源库和目标库连接都正常且权限到位
很多迁移卡在第一步,不是功能不会用,而是连接或权限没配对:
- 源库账号必须有
SELECT权限,否则连表字段都读不出来,数据传输会报 “无法获取表结构” 或直接跳过该表 - 目标库账号至少要有
CREATE、INSERT、DROP(如果勾选了“创建前删除目标对象”);缺CREATE会导致建表失败,错误信息通常是Access denied for user 'xxx'@'%' to database 'xxx' - 目标数据库必须提前建好,且字符集建议与源库一致(如
utf8mb4),否则中文字段可能变成???;Navicat 不会自动帮你建库,也不会校验字符集是否匹配 - 如果走 SSH 隧道,Navicat 连接配置里“连接方式”必须选
SSH,且隧道本地端口不能被其他程序占用(常见冲突端口:3306、2222)
启动 数据传输 时方向别选反
Navicat 不自动推断流向,“左边是源、右边是目标”是硬规则,选反了就是把测试库清空再写进生产库——真有人干过这事。
- 打开
工具 → 数据传输,左侧“源”选线上库连接,右侧“目标”选测试库连接 - 下方“源数据库”和“目标数据库”下拉框要分别点开选,不能默认同名——比如源是
prod_user,目标可以是test_user_v2 - 如果目标库已存在同名表,默认行为是清空再插入;若想追加数据,得取消勾选
创建前删除目标对象,并确保目标表结构与源表完全一致,否则INSERT SELECT会因字段数/类型不匹配失败
高级设置里几个关键开关要按需开闭
默认设置适合小表全量迁移,但大表或特殊场景下必须调:
-
包含外键限制建议勾选,否则外键约束丢失,后续INSERT可能因父表缺失报错Cannot add or update a child row: a foreign key constraint fails -
使用交易对大表迁移慎用:开启后失败会回滚全部,但耗内存且可能锁表太久;数据量超 10 万行建议关掉,靠日志定位失败点更可控 -
运行多重插入语句和使用扩展插入语句必须一起开,否则单条INSERT插 1 行太慢;但目标 MySQL 版本低于 5.7 时,VALUES (...),(...)可能被截断,此时改用使用完整插入语句 -
遇到错误继续只在调试阶段开,正式迁移必须关——它会跳过报错行,导致数据不一致却无提示
字段类型不兼容时必须手动调映射
Navicat 自动匹配同名字段,但类型不兼容时不会报错,而是静默失败或插错值:
- 比如源表
created_at DATETIME,目标表是ctime TIMESTAMP,不调映射会直接报Data too long for column 'ctime'或插成0000-00-00 00:00:00 - 点击
高级 → 调整字段映射,在对应字段右侧点“表达式”,填UNIX_TIMESTAMP(created_at)或FROM_UNIXTIME(ctime)做转换 - 目标为 PostgreSQL 时,MySQL 的
TINYINT(1)默认映射成BOOLEAN,但若源数据含 2/3 等非 0/1 值,就得改成SMALLINT并手动写转换表达式
真正容易被忽略的是:跨服务器迁移没有“回滚”概念,数据传输 过程中目标库写入不可逆,哪怕只差最后一张表没传完,前面的表也已经覆盖了。所以务必先在空库上试跑一次,用 SELECT COUNT(*) 对比每张表行数,再检查几条关键记录的字段值是否正确——尤其是时间、JSON、BLOB 类型。


















