必须将MySQL服务端、连接层、表结构、字段定义四者全部对齐到utf8mb4,缺一不可;仅改其中一两处仍会报错,需通过SHOW VARIABLES和SHOW CREATE TABLE逐层验证character_set_client、connection、results、server及字段CHARACTER SET是否均为utf8mb4。
必须把 MySQL 服务端、连接层、表结构、字段定义四者全部对齐到 utf8mb4,缺一不可;只改其中一两处,错误照常报。
执行 SHOW VARIABLES LIKE 'character_set%';,重点盯这四个值:character_set_client、character_set_connection、character_set_results、character_set_server。只要有一个是 utf8(不是 utf8mb4)或 latin1,就可能触发错误。
再运行 SHOW CREATE TABLE your_table;,确认每个中文字段的定义里是否明确写着 CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci。很多表看着“用了 utf8”,实际字段还是 utf8 或 latin1,插入汉字时直接被截断。
'xE5xBCxA0' 这类三字节序列 → 基础中文都没走通,大概率是客户端或字段层卡在 utf8
'xF0x9Fx98x80' 这种四字节 → 明确指向 emoji 或生僻字,说明链路里至少有一环没上 utf8mb4
ALTER TABLE your_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; 会重建整张表,大表耗时且锁表;更重要的是,它不保证旧字段的定义被刷新——字段本身仍可能保留 CHARACTER SET utf8 的元数据。
真正生效的是逐字段修改:
ALTER TABLE your_table MODIFY COLUMN name VARCHAR(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL;
NOT NULL、默认值等一个都不能少,漏了可能重置约束MODIFY COLUMN 会自动保留;但若用 CHANGE COLUMN,需手动补全索引定义MySQL 服务端全配成 utf8mb4,但应用连接不声明,照样报错。这不是配置遗漏,是协议层根本没谈拢。
characterEncoding=utf8mb4(不是 utf8),且 useUnicode=true 不可省略charset='utf8mb4';写成 'utf8' 或留空都无效PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4",光设 DSN 里的 charset 不起作用{ charset: 'utf8mb4' },环境变量或全局配置无效仅改 [mysqld] 下的 character-set-server=utf8mb4 不够。客户端行为由 [client] 和 [mysql] 段控制:
[client]default-character-set = utf8mb4[mysql]default-character-set = utf8mb4[mysqld]character-set-server = utf8mb4collation-server = utf8mb4_unicode_ci
utf8mb4,输入中文也可能被客户端转错 —— 此时先在 MySQL 里执行 SET NAMES utf8mb4; 再插入,可临时验证character_set_server 不会更新utf8mb4_unicode_ci 比 utf8mb4_general_ci 更准,尤其涉及中文排序或比较时最复杂的点不在某一步操作,而在于五层(client / connection / results / server / column)必须全部对齐。漏掉任意一层,比如字段改了但连接没声明,或者连接声明了但服务端配置仍是 utf8,错误就会原样复现。