乱码本质是字符集在某层被错解,必须统一character_set_client、connection、results为utf8mb4;登录命令行执行show variables like 'character%'确认三者,任一非utf8mb4即导致导入乱码,改表无效。

乱码不是数据坏了,是字符集在某一层被错解了——必须定位到具体哪一层错位,再针对性修复。
查清三件套:character_set_client/connection/results 是否全为 utf8mb4
登录 MySQL 命令行(别用 Navicat 或 DBeaver 代查),执行:SHOW VARIABLES LIKE 'character%';
只看这三项:character_set_client、character_set_connection、character_set_results。只要其中任意一项不是 utf8mb4(比如是 latin1、utf8 或 gbk),导入时中文就会在连接层被截断或误转,后续改表也白搭。
- 如果终端本身不是 UTF-8 编码(如 Windows CMD 代码页是 936),
character_set_client即使设成utf8mb4也无效,得先改终端编码 -
character_set_server和character_set_database是存储层默认值,影响新库新表,但不决定已有数据能否正确显示 - 图形工具常自动声明字符集,掩盖真实问题;命令行才是唯一可信入口
临时救急:用 SET NAMES utf8mb4 对齐当前会话
在导入前,先执行:SET NAMES utf8mb4;
它等价于同时设置 client、connection、results 为 utf8mb4,能立刻让 INSERT 和 SELECT 中文正常。但注意:
– 只对当前连接有效,断开重连就失效
– 不修复已存的乱码数据,只防止新导入再乱
- 如果执行后仍乱码,说明你导出的数据文件本身编码不是 UTF-8(比如用记事本另存为 ANSI 导出的 SQL),得先用 VS Code 或 Notepad++ 转成 UTF-8 without BOM 再重试
- 某些旧版 MySQL 客户端不支持
utf8mb4,报错 “Unknown character set” 时,先确认 MySQL 版本 ≥ 5.5.3
永久生效:my.cnf 必须加 skip-character-set-client-handshake
配置文件里光写 character-set-server = utf8mb4 不够,客户端可能硬编码发 latin1,服务端默认会照单全收。必须在 [mysqld] 段落加这一行:skip-character-set-client-handshake = ON
- 它强制忽略客户端声明的字符集,所有连接统一按服务端设定走
-
[client]段落加default-character-set = utf8mb4,确保 mysql 命令行工具启动就用对编码 - Linux 下重启用
sudo systemctl restart mysql,Windows 下必须通过服务管理器重启,直接 kill 进程不加载新配置
修复已乱码的数据:不能只改表结构,要按原错编码还原再转存
如果数据已经导入并显示为 æ‘æˆ‘ 这类 mojibake,说明字节被错误解码过两次。此时 ALTER TABLE ... CONVERT TO CHARACTER SET utf8mb4 会把错码当真码再转一次,结果更糟。
- 先用
SELECT HEX(column_name) FROM table_name LIMIT 1;看原始字节,比如显示E68891E68891,这是 UTF-8 字节被当成 latin1 解出来的结果 - 导出时指定原始编码(如用 mysqldump 加
--default-character-set=latin1),再用 iconv 转成 UTF-8,最后以utf8mb4导入 - 系统表(如
mysql.user)乱码风险高,操作前必须mysqldump --all-databases --single-transaction > backup.sql全量备份
真正卡住人的从来不是“怎么改”,而是分不清哪一层在错——客户端编码、连接参数、服务端默认、表结构、字段定义、甚至导出文件本身,六层里只要漏一层,乱码就必然重现。











