MySQL中文乱码主因是character_set_results与客户端解码不一致,需确保其值为utf8mb4,并匹配终端、驱动及JDBC等各层编码配置。
MySQL 查询结果出现中文乱码,先看 character_set_results 是否被覆盖
客户端发请求后,mysql 会按 character_set_results 把结果转成对应编码再发出去。很多乱码不是数据库存错了,而是这层转换崩了——比如你用 set names utf8mb4,它其实等价于同时设 character_set_client、character_set_connection 和 character_set_results;但如果你只改了前两个,character_set_results 还卡在 latin1,select 出来的中文就变成 ??? 或一堆问号。
实操建议:
- 连接建立后立刻执行
SHOW VARIABLES LIKE 'character_set%';,重点盯character_set_results的值,它必须和你的终端/应用实际解码方式一致(通常是utf8mb4) - 不要依赖配置文件里全局设置,某些客户端(如旧版 MySQL Workbench、部分 Python DB-API 驱动)会在连接时悄悄重置
character_set_results - PHP 的
mysqli要显式调用mysqli_set_charset($conn, 'utf8mb4'),光设SET NAMES不够稳定
Python pymysql / mysql-connector-python 连接时没设 charset,结果集默认当 latin1 解
这两个库默认不指定字符集时,底层仍走 MySQL 协议默认的 latin1 编码协商。即使数据库表是 utf8mb4、连接字符串写了 charset=utf8mb4,只要参数名写错或位置不对,驱动就忽略——比如 pymysql.connect(..., charset='utf8mb4') 是对的,但 encoding='utf8mb4' 就完全无效。
实操建议:
-
pymysql必须传charset='utf8mb4',且不能和init_command='SET NAMES utf8mb4'混用,后者可能被重复执行导致冲突 -
mysql-connector-python要用charset='utf8mb4',不是collation或unicode参数;若用字典传参,键名必须是字符串'charset',不能是变量 - 查完数据后,用
type(row[0]), row[0].encode('latin1').decode('utf8mb4', errors='replace')快速验证是否真乱码:如果encode('latin1')不报错,说明驱动确实把 UTF-8 字节当 Latin-1 读了
MySQL 客户端命令行(mysql CLI)启动时未指定 --default-character-set,终端显示仍是乱码
CLI 工具本身不读 my.cnf 里的 [client] 段 charset 设置,除非你加 --default-character-set=utf8mb4 启动,或者在 ~/.my.cnf 的 [client] 下写 default-character-set = utf8mb4(注意不是 character-set-client-handshake)。
实操建议:
- 直接运行
mysql --default-character-set=utf8mb4 -u root -p,比改配置更可控 - macOS 终端或 Windows Terminal 如果本身编码不是 UTF-8,即使 MySQL 返回正确字节,终端也渲染失败——检查终端当前编码:
locale(Linux/macOS)或chcp(Windows),确保是UTF-8(65001) - 别信
STATUS命令里显示的Current pager或Server characterset,它们不反映结果集实际编码,要看character_set_results
Java JDBC URL 里 useUnicode=true&characterEncoding=utf8 失效,其实是 utf8mb4 没配全
MySQL JDBC 驱动 5.1+ 默认不支持 4 字节 UTF-8(即 utf8mb4),只认 utf8(其实是 MySQL 的阉割版,最多 3 字节)。URL 里写 characterEncoding=utf8 看似对了,实际连的是 utf8 编码通道,遇到 emoji 或生僻汉字就截断或替换成 ?。
实操建议:
- JDBC URL 必须包含
useUnicode=true&characterEncoding=utf8mb4&serverTimezone=UTC,缺一不可;characterEncoding值必须是utf8mb4,不是UTF-8或utf8 - Driver class 要用
com.mysql.cj.jdbc.Driver(8.x),老版com.mysql.jdbc.Driver对 utf8mb4 支持不完整 - Spring Boot 的
application.yml中,url字段要整个 URL 转义,比如&得写成&,否则 YAML 解析器会切掉参数










