ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4 会重写所有字段,而 ALTER TABLE t CHARACTER SET = utf8mb4 仅修改表默认字符集、不影响现有列;后者常被误用导致字段仍为 latin1。

ALTER TABLE 修改字符集时,CONVERT TO 和 CHARACTER SET 的区别必须分清
直接改表字符集,不是所有写法效果都一样。ALTER TABLE t CONVERT TO CHARACTER SET utf8mb4 会重写所有字段(含列定义、索引、注释),而 ALTER TABLE t CHARACTER SET = utf8mb4 只改表默认字符集,已有列完全不动——后者常被误用,改完发现字段还是 latin1。
-
CONVERT TO是真正批量“转换内容”,适合从旧编码迁移到新编码(如utf8→utf8mb4) -
CHARACTER SET =只影响后续新增列的默认值,对存量字段无任何作用 - 如果表里有
ENUM或SET字段,CONVERT TO会尝试按新字符集重新解析枚举值,可能报错:Incorrect string value,得先手动清理非法值
批量修改多张表,别手写 N 条 ALTER TABLE
用 SQL 拼接生成语句最稳,避免漏表或拼错名。核心是查 information_schema.tables 过滤目标库+当前字符集,再拼出 CONVERT TO 语句。
- 先确认要改哪些表:
SELECT CONCAT('ALTER TABLE `', table_name, '` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;') FROM information_schema.tables WHERE table_schema = 'your_db' AND table_collation NOT LIKE 'utf8mb4%'; - 执行前务必加
SELECT预览,别直接INSERT INTO ... SELECT批量执行——万一条件写错,全库乱码就回不去了 - 大表慎用:单次
CONVERT TO会锁表(MySQL 5.6+ 支持ALGORITHM=INPLACE的场景有限,TEXT/BLOB列存在时基本都会降级为 COPY)
COLLATE 不只是排序规则,它影响索引行为和 WHERE 查询结果
改 COLLATE 不等于只改“看起来怎么排”,它直接决定字符串比较是否大小写敏感、是否忽略重音符号。比如把 utf8mb4_general_ci 换成 utf8mb4_0900_as_cs,WHERE name = 'ABC' 就不再匹配 'abc'。
- 线上业务改
COLLATE前,必须检查所有涉及字符串比较的 SQL,尤其是JOIN条件和GROUP BY字段 -
utf8mb4_unicode_ci在 MySQL 8.0+ 已被标记为废弃,推荐用utf8mb4_0900_as_cs(区分大小写+重音)或utf8mb4_0900_ai_ci(不区分) - 如果某列已有索引,改
COLLATE后索引仍可用,但查询优化器可能因 collation 变更选择不同执行计划——建议改完跑一遍EXPLAIN关键查询
真正容易被跳过的一步:检查连接层与客户端配置
表和字段字符集全改成 utf8mb4 了,但应用连进来用的是 latin1 连接,照样存乱码、查不出数据。
- 确认 MySQL 服务端配置:
character_set_server和collation_server必须设为utf8mb4/utf8mb4_0900_ai_ci - 应用连接串里必须显式指定:
?charset=utf8mb4(PHP PDO)、useUnicode=true&characterEncoding=utf8mb4(JDBC) -
SHOW VARIABLES LIKE 'character\_set%'查出来的client、connection、results三项必须全是utf8mb4,缺一个都白改
字符集迁移不是改完表就结束的事,它是从存储层、传输层到应用层的链路协同。中间任何一环掉链子,前面所有 ALTER TABLE 都只是在制造假象。


















