MySQL默认字符集非utf8mb4,需服务端、数据库、表、列、连接五层编码全部对齐才能正确存储emoji;配置文件修改需同步client[mysqld]三段,并手动转换旧库表及显式设置连接层字符集。

MySQL 默认字符集不是 utf8mb4,直接改配置文件不生效是常态——核心问题在于服务端、数据库、表、列、连接这五层编码必须全部对齐,漏一层就存 emoji 失败或乱码。
确认当前实际生效的字符集层级
很多人只看 SHOW VARIABLES LIKE 'character_set%',但这是服务端默认值,不代表你建的库/表用的真是它。真正决定存储行为的是创建时显式指定或继承的字符集:
-
character_set_server:影响新创建数据库的默认字符集(但已有库不变) -
collation_server:配合上者,决定默认排序规则,建议配utf8mb4_unicode_ci或utf8mb4_0900_as_cs(MySQL 8.0+) - 每个数据库有自己的
DEFAULT CHARACTER SET,用SHOW CREATE DATABASE db_name查 - 每张表也有自己的
CHARSET和COLLATE,用SHOW CREATE TABLE t查 - 连接层(client/connection)的字符集由
SET NAMES utf8mb4或连接字符串参数控制,和服务器变量无关
修改 MySQL 配置文件(my.cnf / my.ini)的关键项
仅改 [mysqld] 段不够,客户端工具(如 mysql 命令行、某些 ORM)会读 [client] 和 [mysql] 段。必须三处同步写:
[client] default-character-set = utf8mb4 [mysql] default-character-set = utf8mb4 [mysqld] character-set-server = utf8mb4 collation-server = utf8mb4_unicode_ci init_connect = 'SET NAMES utf8mb4' skip-character-set-client-handshake = TRUE
注意:skip-character-set-client-handshake 强制忽略客户端声明的字符集,防止应用传 latin1 导致插入乱码;init_connect 对普通用户生效,但对 root 或带 SUPER 权限的账号无效(需单独处理)。
解析 MySQL 8.0 的 DDL 脚本,并将表结构导出为 Excel 格式。适用于用户需将 MySQL 的 `CREATE TABLE` 语句转换为结构化的 Excel 文件场景,导出内容包含字段名、数据类型、长度及精度等信息。支持多张表的批量处理,每张表对应 Excel 中的一个独立工作表。适用于数据库文档编写、数据字典生成及模式分析等任务。
已有数据库和表批量转成 utf8mb4
改完配置重启 MySQL 只影响新建对象,旧库旧表仍保持原字符集。必须手动转换,且顺序不能错:
- 先改数据库:
ALTER DATABASE db_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; - 再逐个改表:
ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; - 如果某列是
TEXT或VARCHAR且定义了CHARACTER SET latin1,上面语句可能失败,得先删掉列级字符集:ALTER TABLE t MODIFY c VARCHAR(255) CHARACTER SET utf8mb4; - 索引字段长度超限?
utf8mb4下一个字符最多占 4 字节,原来VARCHAR(255)的索引可能爆 767 字节限制(InnoDB 默认),要调大innodb_large_prefix并用ROW_FORMAT=DYNAMIC
连接层必须显式声明 utf8mb4
即使服务端全设对了,PHP 的 mysqli、Python 的 pymysql、Java 的 JDBC 都不会自动用 utf8mb4。常见漏点:
- PHP mysqli:
$mysqli->set_charset('utf8mb4')或连接 DSN 加;charset=utf8mb4 - Python pymysql:
charset='utf8mb4'必须传进connect() - JDBC URL:加
?characterEncoding=utf8mb4&serverTimezone=UTC,useUnicode=true也得带上 - 命令行登录后立即执行:
SET NAMES utf8mb4;(否则INSERTemoji 会报Incorrect string value)
最隐蔽的坑:某些老版本 MySQL 客户端库(如旧版 mysql-python)根本不支持 utf8mb4,会静默降级成 utf8(即 utf8mb3),连报错都没有。

















