当前连接乱码是解码链断裂所致,须检查character_set_client、character_set_connection、character_set_results三项是否均为utf8mb4,并确认表字段、客户端工具及orm驱动均正确配置utf8mb4编码。

查当前连接实际生效的三变量
乱码不是数据坏了,是解码链断了——必须先看这条连接到底用什么字符集在传数据。别信配置文件或建表语句,执行:SHOW VARIABLES LIKE 'character_set_%';,只盯这三项:character_set_client、character_set_connection、character_set_results。
如果其中任意一个是 latin1、gbk 或 utf8(注意:不是 utf8mb4),而你的应用/终端实际发的是 UTF-8 字节,那 SELECT 出来的中文必乱。
- 常见现象:SELECT 出来是问号或 Mojibake(如“æäº›æå”),但
SELECT HEX(col)显示的是合法 UTF-8 字节(如E69FE4BAA7),说明写入没问题,只是读取时解错了 -
character_set_client决定 SQL 字符串怎么被 MySQL 解析;character_set_connection决定字段值在比较/转换时用什么编码;character_set_results决定返回给客户端的字节按什么编码解 - 三者不一致,WHERE 条件就可能匹配失败:比如你写
WHERE name = '张三',但character_set_client是latin1,MySQL 就把这 6 个字节当 Latin-1 处理,根本找不到 UTF-8 存储的值
确认表和字段是否真用了 utf8mb4
即使连接层全对了,表结构本身用错字符集,插入时就已损坏。建表语句里没显式写 CHARACTER SET utf8mb4,哪怕数据库默认是 utf8mb4,也可能继承错。
执行:SHOW CREATE TABLE your_table;,检查字段定义里有没有 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci。没有?那就得改:
ALTER TABLE t MODIFY COLUMN name VARCHAR(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;- 别只改表级:
ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;会批量改所有文本字段,但要注意已有乱码数据不会自动修复 -
utf8不等于utf8mb4:前者最多存 3 字节 UTF-8 字符(不支持 emoji 和部分生僻汉字),后者才真正完整
检查客户端工具或终端的解码设置
Navicat、DBeaver、命令行 mysql 客户端这些工具本身不决定编码,它们只是把服务器返回的字节流,按自己设定的“显示编码”渲染出来。所以即使数据库和连接都设对了,工具端解码错,照样乱码。
- Navicat:右键连接 →「编辑连接」→「高级」页签 → 勾选「使用 MySQL 字符集」并确保下拉选的是
utf8mb4 - DBeaver:连接属性 →「Driver properties」→ 找到
characterEncoding,值设为utf8mb4;同时主菜单「Window → Preferences → General → Workspace」里文本文件编码也要设为 UTF-8 - 命令行:
mysql --default-character-set=utf8mb4 -u root -p,否则默认用latin1;还要确认你本地终端(如 iTerm、Windows Terminal)本身支持 UTF-8
排查 ORM 或驱动层是否漏了 charset 参数
很多框架默认不自动发 SET NAMES utf8mb4,靠服务端配置撑不住。连接一建立就得立刻声明编码,否则前几条 SQL 就可能走错路。
- Python pymysql:
connect(host='...', charset='utf8mb4'),漏掉就退化成latin1 - Java JDBC URL:
jdbc:mysql://host/db?useUnicode=true&characterEncoding=utf8mb4(注意是utf8mb4,且&在 XML/properties 中要转义) - PHP PDO DSN:
mysql:host=localhost;charset=utf8mb4;mysqli 则需$conn->set_charset('utf8mb4')在 connect() 后立刻调用 - Spring Boot:
spring.datasource.url里参数拼接错误(比如&没转义成&)会导致后续参数被截断,characterEncoding根本不生效
SET NAMES 都只影响之后的查询**。如果你的应用复用连接池,而某个连接初始化时没带 charset,它就会一直错下去——不是重启服务就能清掉的。










