新项目默认用utf8mb4_0900_ai_ci,因其基于Unicode 9.0 UCA算法,对重音和大小写均不敏感,能正确处理中、西欧、阿拉伯、越南文等多语言混合排序与模糊匹配;但需逐层覆盖服务器→数据库→表→列,否则查询行为不一致。

直接结论:新项目默认用 utf8mb4_0900_ai_ci,但必须逐层确认生效位置,否则查询行为会不一致。
为什么 utf8mb4_0900_ai_ci 是多数场景的起点
它基于 Unicode 9.0 的 UCA 算法,对重音(如 é 和 e)和大小写(A 和 a)都不敏感,能正确处理中文、西欧、阿拉伯、越南文混合排序。比如 WHERE name LIKE '%joão%' 或 ORDER BY surname 不会漏匹配或错序。
但注意:它不适合需要严格区分的场景——比如密码校验、法律文书比对,此时应改用 utf8mb4_0900_as_cs 或显式加 BINARY 修饰。
哪些操作会绕过你设的排序规则
即使服务器、库、表、列全设成 utf8mb4_0900_ai_ci,以下情况仍可能失效:
- 连接未声明字符集:命令行登录后没执行
SET NAMES utf8mb4;,客户端默认用latin1解析输入,WHERE title = 'café'实际传入的是乱码字节 - 索引未重建:COLLATE 改变后,原有索引不会自动更新;用
SHOW INDEX FROM users;查看Collation列是否为A(表示可用),否则需手动重建:ALTER TABLE users DROP INDEX idx_name, ADD INDEX idx_name(name); - 字符串字面量隐式转换:
SELECT * FROM users WHERE name = 'João' COLLATE utf8mb4_bin;这种写法强制走二进制比较,跳过你设的_ai_ci规则
如何逐层覆盖而不留死角
排序规则继承链是:服务器 → 数据库 → 表 → 列 → 字符串常量。只改其中一层,其他层仍按旧规则执行比较。
- 服务器级(影响所有新建数据库):在
my.cnf中设置:[mysqld] character-set-server = utf8mb4 collation-server = utf8mb4_0900_ai_ci
- 数据库级(影响后续新建表):
ALTER DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci; - 表级(影响后续新建列):
ALTER TABLE users CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;—— 注意:大表会锁表重写 - 列级(最细粒度,强制生效):
ALTER TABLE users MODIFY COLUMN name VARCHAR(255) COLLATE utf8mb4_0900_ai_ci;—— 必须重复声明类型,否则丢失定义
升级 MySQL 5.7 到 8.0 后的典型报错怎么解
常见错误:ERROR 1267 (HY000): Illegal mix of collations (utf8mb4_general_ci,IMPLICIT) and (utf8mb4_0900_ai_ci,IMPLICIT),本质是函数(如 FIND_IN_SET)两边字段或变量用了不同 COLLATE。
临时修复方式(不推荐长期用):
SELECT * FROM t01 WHERE FIND_IN_SET(b_code, @xxx COLLATE utf8mb4_0900_ai_ci);
根本解法是统一底层列的 COLLATE,并检查所有变量初始化语句是否带 COLLATE 显式声明。尤其注意存储过程、触发器里拼接的字符串常量,默认按会话 COLLATE 解析,容易被忽略。
真正难的不是选哪个规则,而是确保从连接建立、数据写入、索引构建到查询执行,每一步都落在同一套规则链上。一个没覆盖的层级,就可能让 utf8mb4_0900_ai_ci 形同虚设。


















