字符集和Collation在生产环境踩过什么坑?
先说结论
生产环境统一用utf8mb4字符集 + utf8mb4_unicode_ci排序规则。不要用utf8(它只支持3字节,不能存emoji)。
先把这段讲顺;面试官追问时,再展开下面的原理和细节。
详细讲解
字符集问题看起来很基础,但它能引发乱码、查询结果错误、索引失效等一系列问题。我在出海业务里被字符集坍过好几次。今天把常见的坑和最佳实践讲清楚。
坑一:utf8不是真正的UTF-8
MySQL的utf8只支持3字节字符,不能存储emoji和某些稀有汉字。4字节的字符会被截断或报错。
我在元宇宙社交App时,用户昵称里带emoji就会插入失败。检查后发现建表时用的是utf8而不是utf8mb4。改为utf8mb4后解决。
-- 检查当前字符集
SHOW CREATE TABLE users\G
-- 修改为utf8mb4
ALTER TABLE users CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
坑二:Collation不一致导致Join索引失效
这是最难发现的坑。如果两张表的Join字段的Collation不一样(比如一个是utf8mb4_general_ci,另一个是utf8mb4_unicode_ci),MySQL会做隐式转换,导致索引失效。
EXPLAIN会显示type=ALL(全表扫描),但你明明加了索引。这个问题我排查了半天才发现是Collation不一致。
解决方案: 统一所有表和字段的Collation。建表规范里必须明确指定。
坑三:出海业务的多语言排序问题
出海业务涉及多语言。utf8mb4_general_ci和utf8mb4_unicode_ci的排序规则不同:
general_ci: 简化版排序,快但不准确。比如德语的ß和ss不等价。
unicode_ci: 按Unicode标准排序,准确但稍慢。推荐出海业务使用。
MySQL 8.0还引入了utf8mb4_0900_ai_ci(基于Unicode 9.0),是8.0的默认Collation。
总结
统一用utf8mb4,统一Collation。建表规范里必须明确指定字符集和Collation。面试时能说清楚“utf8不是真正的UTF-8”和“Collation不一致导致索引失效”这两个坑,说明你是真正踩过的。
下一篇聊一个数据开发经常遇到的场景:MySQL的Buffer Pool怎么调优?内存分配有什么讲究?
你们被字符集坍过吗?评论区聊聊~
关注「Wood聊大数据」| 9年大数据老兵,聊技术、聊职场、聊成长