仅修改character-set-server=utf8mb4不足以解决中文显示问号问题,必须同步将character_set_client、character_set_connection、character_set_results三个会话级字符集统一设为utf8mb4,否则客户端仍用latin1解码导致问号。

只改 character-set-server=utf8mb4 不足以解决中文显示问号问题,必须同步确保 client/connection/results 三层会话级字符集也统一为 utf8mb4,否则客户端仍用 latin1 解码 utf8mb4 字节流,必然变成 ?。
为什么改了 character-set-server 还是显示问号
因为 character-set-server 只控制新数据库的默认字符集,不改变当前连接行为。MySQL 实际读写数据时依赖的是三个会话变量:character_set_client、character_set_connection、character_set_results。如果它们仍是 latin1(MySQL 5.7 及以前默认值),哪怕表和字段全是 utf8mb4,服务端返回的字节也会被客户端错误解释成乱码或问号。
常见现象:
- 执行
SHOW VARIABLES LIKE 'character\_set%';后发现character_set_client是latin1 - 用
SELECT查出中文字段显示为???或空格,但LENGTH()返回值明显大于字符数(说明字节没丢,只是解码错) - 插入成功且无报错,但查出来就是问号——这是典型的“存对了、读错了”
怎么验证当前连接实际生效的字符集
登录 MySQL 后直接运行:
SHOW VARIABLES LIKE 'character\_set%';
重点关注这三行是否都为 utf8mb4:
character_set_clientcharacter_set_connectioncharacter_set_results
只要其中任意一个不是 utf8mb4,就可能造成问号。注意:character_set_database 和 character_set_server 即使是 utf8mb4 也不代表连接层安全。
临时修复:用 SET NAMES 立刻生效
在当前会话中执行:
SET NAMES utf8mb4;
这条命令等价于同时设置:
SET character_set_client = utf8mb4;SET character_set_connection = utf8mb4;SET character_set_results = utf8mb4;
执行后立刻能查出正确中文,但退出重连即失效。适合调试或脚本开头手动加一句,不适合生产环境长期依赖。
永久修复:配置文件 + 客户端显式声明
仅改 [mysqld] 段的 character-set-server=utf8mb4 是不够的,还必须覆盖客户端行为:
- 在
[client]段加default-character-set=utf8mb4(MySQL 8.0+ 已弃用,建议用[mysql]段的default-character-set) - 在
[mysql]段加default-character-set=utf8mb4,影响命令行客户端 - 应用程序连接串必须显式声明,例如 JDBC:
?useUnicode=true&characterEncoding=utf8mb4;PHP PDO:charset=utf8mb4在 DSN 中 - GUI 工具如 MySQL Workbench 需在 Connection → Advanced → Others 添加
characterSet=utf8mb4
改完配置必须重启 mysqld 服务,且所有已存在的连接不会自动更新,需重新建立连接才生效。
最容易被忽略的一点:即使服务端、连接层、表结构全设成 utf8mb4,如果字段定义里写了 CHARACTER SET latin1,那这个字段还是按 latin1 存储——SHOW FULL COLUMNS FROM table_name 中的 Collation 列才是最终依据。


















