字符集决定存储内容,排序规则决定比较方式;utf8mb4支持emoji和生僻字,utf8mb4_0900_ai_ci忽略重音与大小写,utf8mb4_bin逐字节比较。

字符集决定存什么,排序规则决定怎么比
字符集(character set)是 MySQL 存储文本的“编码字典”:它定义了每个字符对应哪一串二进制数据。比如 utf8mb4 能存 emoji 和生僻汉字,而 utf8(MySQL 里的伪 utf8)只能存前 65536 个 Unicode 字符,遇到 ? 或 “?” 就直接截断或报错。
排序规则(collation)则是配套的“比较说明书”:它告诉 MySQL 两个字符串相等吗、谁该排前面。例如 utf8mb4_0900_ai_ci 认为 'café' 和 'cafe' 相同(忽略重音+大小写),而 utf8mb4_bin 按字节逐位比,哪怕只差一个字节也判不等。
配置错了会出哪些具体问题
字符集/排序规则配错不是“看起来不太对”,而是直接引发可复现的故障:
– 插入 emoji 报 Incorrect string value 错误
– WHERE name = '张三' 查不到数据,因为客户端用 latin1 发请求,服务端用 utf8mb4 存,中间解码错位
– ORDER BY title 把“苹果”排在“香蕉”后面,只因用了 utf8mb4_general_ci(拼音排序不准)而非 utf8mb4_zh_0900_as_cs
– SELECT DISTINCT email 漏掉 'User@EXAMple.com',因 _ci 规则把大小写视为相同,去重时合并了
必须分层配置,且优先级明确
MySQL 的字符集和排序规则有五层,从高到低覆盖:列 > 表 > 数据库 > 服务器 > 连接。高优先级设置会覆盖低层,但不会自动“向下渗透”。
常见误区是只改了 character_set_server,就以为所有新库都安全了——其实只是新库默认继承它,一旦建库时没显式指定,又恰好之前有旧配置残留,仍可能创建出 utf8 库。
实操建议:
– 服务端配置(my.cnf)加这两行:
[mysqld]<br>character-set-server = utf8mb4<br>collation-server = utf8mb4_unicode_ci
– 创建数据库时强制声明:
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci– 建表时别省略:
CREATE TABLE t (name VARCHAR(100)) CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci– 关键字段如用户名、邮箱,可单独设更严格的规则:
ALTER TABLE users MODIFY email VARCHAR(255) COLLATE utf8mb4_bin(避免大小写混用导致重复注册)
已有数据迁移要格外小心
对已存在的表执行 ALTER TABLE ... CONVERT TO CHARACTER SET 不是改个元数据那么简单——它会真正读取每一行内容,按新字符集重新编码,再写回磁盘。这意味着:
– 表会被锁住,大表可能阻塞业务数小时
– 如果原数据里混有非法编码(比如用 latin1 存过中文),转换后变成乱码无法恢复
– 索引会重建,需额外磁盘空间
安全做法是:
• 先用 SHOW CREATE TABLE 确认当前字符集
• 导出数据为 SQL 文件,用文本编辑器检查是否有乱码痕迹
• 在测试库完整走一遍 CONVERT TO + 查询验证
• 生产环境选低峰期,并确保有可快速回滚的备份









