MySQL默认字符集未生效,因character-set-server必须置于[mysqld]段;utf8mb4替代utf8支持4字节Unicode;需验证运行时变量并显式配置客户端编码。

MySQL 启动时默认字符集没生效?检查 my.cnf 的配置层级
MySQL 字符集不生效,八成是因为配置写错了位置。mysqld 服务只读取 [mysqld] 段下的 character-set-server 和 collation-server,而客户端连接行为受 [client] 和 [mysql] 段影响——但它们**不决定服务端默认值**。
-
character-set-server=utf8mb4必须放在[mysqld]下,否则新建数据库/表仍用 latin1 -
collation-server=utf8mb4_unicode_ci要与字符集匹配,不能配成utf8mb4_general_ci(已弃用)或utf8mb4_0900_as_cs(区分大小写,易出兼容问题) - Windows 下注意配置文件名可能是
my.ini;Linux 下常见路径为/etc/my.cnf或/etc/mysql/mysql.conf.d/mysqld.cnf - 改完必须重启
mysqld,仅 reload 不会重载字符集参数
连接时还是乱码?确认客户端显式声明了 charset=utf8mb4
即使服务端设对了,应用连上来不指定编码,MySQL 仍按 handshake 阶段协商的默认值通信——这个默认值可能仍是 latin1。尤其 JDBC、PHP mysqli、Python mysql-connector 等驱动,不显式传参就容易踩坑。
- JDBC URL 加
?characterEncoding=utf8mb4&serverTimezone=UTC,缺一不可(characterEncoding控制 client charset,serverTimezone防止时间字段错乱) - PHP mysqli 连接后立即执行
$mysqli->set_charset('utf8mb4'),不能只靠init_connect - 命令行客户端启动时加
--default-character-set=utf8mb4,否则mysql -u root -p默认用系统 locale 对应编码 -
init_connect='SET NAMES utf8mb4'可作为兜底,但它对 SUPER 权限用户无效,且无法覆盖 PRECEDE connection 的认证阶段编码
已有库表乱码怎么办?别直接 ALTER TABLE ... CONVERT TO
直接 CONVERT TO 在数据实际是 latin1 编码却标记为 utf8 的情况下,会导致二次转码,中文全变问号或乱码。必须先确认当前存储的真实字节和元数据标记是否一致。
- 查真实编码:执行
SHOW CREATE TABLE tbl_name,看CHARACTER SET和COLLATION字段;再用SELECT HEX(col) FROM tbl_name LIMIT 1看中文字段是否为C3A4C2B8C2A6类似结构(utf8mb4 正确存储)还是E4B8ADE69687(原始 UTF-8 字节被当 latin1 存) - 若标记错误但字节正确(如表声明 latin1,实存 UTF-8 字节),应先
ALTER TABLE tbl_name CONVERT TO CHARACTER SET binary清除标记,再CONVERT TO CHARACTER SET utf8mb4 - 若标记和字节都错(如原先是 GBK 存入,又误标 utf8),需导出为二进制、用 iconv 转码、再导入,无法纯 SQL 修复
utf8mb4 为什么必须设?utf8 在 MySQL 里根本不是真 UTF-8
MySQL 的 utf8 是阉割版,最多存 3 字节字符(U+0000–U+FFFF),不支持 emoji、古汉字、数学符号等 4 字节 Unicode 字符。从 5.5.3 起官方就推荐 utf8mb4,但很多旧配置和 ORM 默认仍用 utf8。
-
utf8mb4占用更多空间:VARCHAR(255) 在utf8mb4下最大实际长度是 255×4=1020 字节,可能触发max_allowed_packet或索引长度限制(InnoDB 单列索引前缀上限 767 字节 → 改用innodb_large_prefix=ON+ 文件格式 Barracuda) - 排序规则选
utf8mb4_unicode_ci而非utf8mb4_general_ci:后者在 MySQL 5.7+ 已废弃,且对某些德语、西班牙语排序不准确 - Docker 部署时记得挂载配置并设置环境变量:
MYSQL_INITDB_CHARSET=utf8mb4,否则初始化库仍用默认 latin1
最常被忽略的是:修改配置后忘记验证运行时值。务必登录后执行 SHOW VARIABLES LIKE 'character\_set%'; 和 SHOW VARIABLES LIKE 'collation%';,以实际输出为准——配置文件写得再对,没生效就是白搭。










