必须同时修改数据库、表、连接三处字符集为utf8mb4,缺一不可;先用SHOW VARIABLES和SHOW CREATE确认各层编码,再ALTER DATABASE和CONVERT TABLE配对执行,PHP连接需显式设utf8mb4,字段级残留及服务参数亦须检查。

必须同时改数据库、表、连接三处字符集,缺一不可;只改其中一两处,乱码照旧。
查清当前字符集链是否断裂
乱码本质是“存储—传输—输出”三环节编码不一致。先确认断在哪:
- 执行
SHOW VARIABLES LIKE 'character_set%',重点看character_set_server、character_set_database、collation_connection是否都为utf8mb4(不是utf8) - 执行
SHOW CREATE DATABASE your_db和SHOW CREATE TABLE your_table,确认DEFAULT CHARSET是utf8mb4 - 若
collation_connection是latin1_swedish_ci或utf8_general_ci,说明连接层已脱节
ALTER DATABASE 和 CONVERT TABLE 要配对执行
只改库不改表,或只改表不改字段,仍可能在特定字段(如 TEXT、VARCHAR)上出乱码:
- 先改库:
ALTER DATABASE your_db CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci - 再改表:
ALTER TABLE your_table CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci - 注意:如果表里有外键,需先
DROP再ADD;执行前务必用mysqldump --default-character-set=utf8mb4备份 - 不推荐只用
MODIFY COLUMN单改某字段——容易漏掉索引、约束隐含的字符集依赖
mysqli::set_charset() 和 PDO DSN 必须显式声明 utf8mb4
PHP 连接 MySQL 时默认用 latin1 建连,即使库表全是 utf8mb4,也会在传输中二次转码:
- mysqli 场景:连接后立刻调用
$mysqli->set_charset('utf8mb4'),不能只靠SET NAMES(它不保证后续预处理语句生效) - PDO 场景:DSN 中必须带
charset=utf8mb4,例如mysql:host=localhost;dbname=test;charset=utf8mb4 - 额外关键项:PDO 构造时加
PDO::ATTR_EMULATE_PREPARES => false,否则模拟预处理会绕过字符集校验 - 避免在配置文件里写
$db->query("SET NAMES utf8")——utf8不支持 emoji,且无法覆盖连接初始化时的默认值
别忽略字段级字符集残留
历史迁移表常存在“库和表是 utf8mb4,但个别字段仍是 latin1”的情况,这类字段插入中文会直接截断或存成问号:
- 用
SHOW FULL COLUMNS FROM your_table检查每列的Collation,非utf8mb4_unicode_ci的都要修正 - 单独改字段:例如
ALTER TABLE your_table MODIFY content TEXT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci - 特别注意
ENUM和SET类型字段,它们的字符集是独立存储的,CONVERT TO不自动处理
最容易被跳过的点:MySQL 服务启动参数 --character-set-server=utf8mb4 和配置文件中的 collation-server = utf8mb4_unicode_ci。重启 mysqld 后才生效,但很多运维直接改完库表就以为结束了。
php免费学习视频:立即使用
踏上前端学习之旅,开启通往精通之路!从前端基础到项目实战,循序渐进,一步一个脚印,迈向巅峰!











