答案是乱码源于客户端、连接层、表字段三者字符集未对齐,需确保character_set_client、character_set_connection、character_set_results及表字段均设为utf8mb4,且应用连接时显式指定charset=utf8mb4。

乱码不是数据库“不支持中文”,而是客户端、连接层、表字段三者字符集没对齐——只要其中一处是 latin1 或旧版 utf8(即 utf8mb3),插入中文大概率变成 ??? 或 \xE6\x88\x91 这类错误。
查清当前实际生效的字符集配置
别信配置文件或建库语句,运行时可能被覆盖。连上 MySQL 后立刻执行:
SHOW VARIABLES LIKE 'character_set%';
重点关注这三项是否全为 utf8mb4:
-
character_set_client:你发 SQL 时,MySQL 认为你用的编码 -
character_set_connection:连接层转码用的中间编码,必须和 client 一致 -
character_set_results:返回结果时用的编码
只要有一个是 latin1 或 utf8(注意不是 utf8mb4),就说明链路断了。
改表字段必须用 CONVERT TO,不能只改表级声明
ALTER TABLE table_name CHARACTER SET utf8mb4 这种写法只改元数据,字段实际存储仍按旧编码,无效。
真正生效的是:
ALTER TABLE your_table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
但要注意:
- 大表会锁表、重建索引、临时磁盘空间翻倍,务必选低峰期
- 若字段有全文索引,
utf8mb4下单列索引长度上限是 767 字节,需配合innodb_large_prefix=ON和ROW_FORMAT=DYNAMIC - 只想改某列(比如
TEXT类型),用MODIFY更可控:ALTER TABLE t MODIFY content TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
但必须重写完整字段定义,否则可能丢NOT NULL或DEFAULT约束
连接层不设 charset=utf8mb4,前面全白搭
即使数据库、表、字段全设成 utf8mb4,只要应用连接没声明字符集,MySQL 仍按 latin1 解析请求——这是最常被忽略的一环。
不同场景写法不同:
- PHP PDO:
mysql:host=localhost;charset=utf8mb4必须写进 DSN - Java JDBC:
jdbc:mysql://localhost:3306/db?useUnicode=true&characterEncoding=utf8mb4,注意&要转义,驱动建议用 8.0+ - 命令行 mysql 客户端:
mysql --default-character-set=utf8mb4 -u root -p,否则默认用latin1 - Navicat:右键连接 →「编辑连接」→「高级」→ 勾选「使用 MySQL 字符集」并选
utf8mb4
漏掉任何一处,character_set_client 就不会变成 utf8mb4,后续所有环节都跟着错。
最容易被忽略的是连接层参数和终端本身编码的双重影响——比如 Windows CMD 默认是 GBK(代码页 936),哪怕连接设了 utf8mb4,如果终端不支持 UTF-8 显示,SQL 语句里的中文在输入阶段就已经变形了。

















