MySQL服务端默认字符集需设为utf8mb4,低版本须修改配置文件并重启;客户端连接必须显式声明utf8mb4;已有库表需按库→表→列顺序ALTER转换;验证需检查client/connection/results三变量及表结构。

MySQL 服务端默认字符集设为 utf8mb4
MySQL 8.0+ 默认已是 utf8mb4,但低版本(如 5.7)仍默认用 latin1 或旧式 utf8(实际是 utf8mb3),不支持 emoji 和部分中文生僻字。必须在启动前通过配置文件强制指定,否则仅靠 SQL 命令无法改变服务端默认行为。
修改 /etc/my.cnf(Linux)或 my.ini(Windows),在 [mysqld] 段落下添加:
[mysqld] character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci
注意:character-set-server 影响新建数据库的默认字符集;collation-server 必须与之兼容,推荐 utf8mb4_unicode_ci(比 utf8mb4_general_ci 更准,且 8.0+ 已弃用后者)。
改完必须重启 MySQL 服务生效:sudo systemctl restart mysqld(或 service mysql restart)。
客户端连接时显式声明 utf8mb4
即使服务端设对了,客户端(如 Python 的 pymysql、Java 的 JDBC、命令行 mysql -u...)若未声明字符集,仍可能走默认 latin1,导致存入乱码或查询截断。
- 命令行连接加参数:
mysql --default-character-set=utf8mb4 -u root -p - Python
pymysql初始化时传参:charset='utf8mb4' - JDBC URL 加
?characterEncoding=utf8mb4&serverTimezone=UTC - PHP
mysqli连接后立即执行:SET NAMES utf8mb4
不建议依赖 init_connect 配置项自动执行 SET NAMES——它对 SUPER 权限用户无效,且无法覆盖已建立连接的会话变量。
已有数据库/表/列批量转 utf8mb4
新配置只影响后续创建的对象。已有库表需手动转换,且必须按「库 → 表 → 列」顺序操作,否则可能报错。
先改数据库默认字符集:
ALTER DATABASE `dbname` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
再逐个改表(含所有字段和索引):
ALTER TABLE `tablename` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
注意:CONVERT TO 会重建表,大表慎用;若提示 Specified key was too long,说明原索引长度超限(utf8mb4 下单字符最多占 4 字节,索引长度限制更紧),需先缩小字段长度或改用前缀索引。
验证是否真正生效
别只看 SHOW VARIABLES LIKE 'character_set%' —— 它只反映服务端配置,不反映当前连接实际使用的字符集。
务必检查三项:
-
SHOW VARIABLES LIKE 'character_set_client':客户端发来的数据按什么解码 -
SHOW VARIABLES LIKE 'character_set_connection':SQL 解析时用什么字符集 -
SHOW VARIABLES LIKE 'character_set_results':返回结果用什么编码发给客户端
三者都应为 utf8mb4。另外,查某张表字段定义:SHOW CREATE TABLE tablename,确认字段显示 CHARACTER SET utf8mb4 而非 utf8。
最容易漏的是客户端连接层——哪怕服务端全配对了,只要应用连上来没带 charset=utf8mb4,照样存进去是乱码,而且查不出来也看不出错。










