Navicat同步后中文变问号或方块,根本原因是源库连接、目标库连接及目标表字段三处字符集未统一为utf8mb4;必须手动在两个连接的“高级”页勾选Override default charset并设为utf8mb4,测试连接成功,并提前将目标表字段单独MODIFY为utf8mb4,同步不改表结构。
Navicat 同步后中文变问号或方块,不是同步功能出错,而是同步过程绕过了字符集协商环节,三处编码没对齐:源库连接声明的编码、目标库连接声明的编码、以及目标表字段实际存储的字符集。必须手动干预,不能依赖“自动同步”。
同步前必须确认两个连接都显式设为 utf8mb4
navicat 的「数据同步」功能不会继承你在「编辑连接」里设置的「mysql 字符集」下拉框值,它默认用 latin1 建立连接,哪怕你测试连接时显示成功。
- 右键源库连接 →「编辑连接」→「高级」→勾选
Override default charset→ 下拉选utf8mb4(不是utf8) - 同样操作配置目标库连接,确保两个连接的「高级」页签里都完成该设置
- 改完必须点「测试连接」并成功,否则设置不生效
- 如果下拉菜单没有
utf8mb4,说明 Navicat 版本低于 v15,需升级或在连接字符串末尾手动加charset=utf8mb4
同步向导里没地方选编码?那就靠脚本补救
Navicat 同步界面不提供“文件编码”或“初始化命令”入口,无法像「运行 SQL 文件」那样手动指定。此时唯一可靠方式是:在同步生成的 SQL 脚本中插入强制声明。
- 勾选同步向导中的「保存为 SQL 文件」,先不执行,拿到 .sql 文件
- 用 VS Code 或 Notepad++ 打开,确认其真实编码(常见为 UTF-8 无 BOM)
- 在文件最顶部第一行插入:
SET NAMES utf8mb4; - 删掉任何类似
SET NAMES latin1或SET character_set_client = gbk的语句 - 再回到 Navicat →「运行 SQL 文件」→ 手动选中该文件 → 点击右上角「编码」按钮 → 明确选
UTF-8(不是自动检测)
目标表字段仍是 latin1?同步不会帮你改表结构
同步只复制数据,不修改目标表的 CHARACTER SET 和 COLLATION。如果目标表建于多年前,字段仍为 latin1_swedish_ci,即使同步脚本执行成功,INSERT 进去的字节也会被错误解释。
- 同步前先查目标表字段编码:
SHOW FULL COLUMNS FROM `target_table`;,看Collation列 - 若某字段 Collation 是
latin1_swedish_ci或为空,执行:ALTER TABLE `target_table` MODIFY `column_name` VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -
TEXT、MEDIUMTEXT类型字段也必须单独MODIFY,CONVERT TO不覆盖它们 - 别用
ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4直接套用——旧数据可能已损坏,先备份再操作
同步后 SELECT 还是问号?立刻检查 connection 层变量
同步完成不代表连接就“活”在 utf8mb4 状态下。Navicat 可能复用旧连接上下文,导致后续查询仍走 latin1 解析路径。
- 断开当前连接,重新连接目标库
- 执行:
SELECT @@character_set_client, @@character_set_connection, @@character_set_results; - 三个值必须全为
utf8mb4;只要有一个是latin1或gbk,说明连接层没生效 - 此时回退到「编辑连接」→「高级」→ 再次确认
Override default charset已勾选且为utf8mb4,并重新测试连接
utf8mb4,或者目标表字段编码没提前对齐,乱码就是确定性结果——不是概率问题,是字节流从源头就错了。











