MySQL :如何选择 utf8mb4 排序规则(Collation)
字符集决定能存什么,排序规则决定怎么比
适用版本:MySQL 5.7+ / MySQL 8.0+
难度级别:中级
阅读时间:25-30 分钟
为什么要关心排序规则? {#为什么要关心排序规则}
一个真实的问题
-- 创建表,使用 utf8mb4_general_ci
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) UNIQUE,
email VARCHAR(100)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
-- 插入数据
INSERT INTO users (username, email) VALUES ('zhangsan', 'zhangsan@example.com');
-- 尝试插入另一条数据
INSERT INTO users (username, email) VALUES ('ZhangSan', 'zhangsan2@example.com');
-- 💥 错误!
-- ERROR 1062 (23000): Duplicate entry 'ZhangSan' for key 'username'
为什么会报错?
因为 utf8mb4_general_ci 中的 ci 表示 case insensitive(大小写不敏感),在这个排序规则下:
zhangsan=ZhangSan=ZHANGSAN唯一索引认为它们是重复的!
排序规则影响什么?
┌─────────────────────────────────────────────────────────┐
│ 排序规则(Collation)影响范围 │
├─────────────────────────────────────────────────────────┤
│ │
│ 1. 字符串比较(WHERE, HAVING) │
│ SELECT * FROM users WHERE username = 'Admin'; │
│ ↓ │
│ 大小写敏感? 'Admin' vs 'admin' vs 'ADMIN' │
│ │
│ 2. 排序(ORDER BY) │
│ SELECT * FROM users ORDER BY username; │
│ ↓ │
│ 排序顺序? 'a' vs 'A' vs 'á' vs 'à' │
│ │
│ 3. 分组(GROUP BY) │
│ SELECT username, COUNT(*) FROM users GROUP BY... │
│ ↓ │
│ 'admin' 和 'Admin' 是同一组? │
│ │
│ 4. 索引(UNIQUE, PRIMARY KEY) │
│ CREATE UNIQUE INDEX idx_username ON users(...) │
│ ↓ │
│ 'user' 和 'User' 算重复? │
│ │
│ 5. JOIN 连接 │
│ SELECT * FROM t1 JOIN t2 ON t1.name = t2.name │
│ ↓ │
│ 连接条件的匹配规则 │
│ │
└─────────────────────────────────────────────────────────┘
utf8 vs utf8mb4:必须了解的历史 {#utf8-vs-utf8mb4}
MySQL 的"utf8"陷阱
⚠️ 重要警告:MySQL 的 utf8 不是真正的 UTF-8!
┌──────────────────────────────────────────────────────────┐
│ MySQL 字符集对比 │
├──────────────────────────────────────────────────────────┤
│ │
│ 标准 UTF-8: │
│ • 可变长度:1-4 字节 │
│ • 支持所有 Unicode 字符 │
│ • Emoji:😀😍🎉 │
│ │
│ MySQL 的 utf8(实际是 utf8mb3): │
│ • 可变长度:1-3 字节(阉割版) │
│ • 不支持 4 字节字符 │
│ • Emoji:❌ 存储失败 │
│ • 生僻汉字:❌ 存储失败(如:𠮷、𡃁) │
│ │
│ MySQL 的 utf8mb4: │
│ • 可变长度:1-4 字节(完整版) │
│ • 支持所有 Unicode 字符 │
│ • Emoji:✅ 完美支持 │
│ • 从 MySQL 5.5.3 开始支持 │
│ • MySQL 8.0 默认字符集 │
│ │
└──────────────────────────────────────────────────────────┘
为什么 MySQL 有这个"bug"?
历史原因:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
2003 年 - MySQL 4.1 引入 utf8 字符集
当时 UTF-8 规范还没完全确定
MySQL 实现时只用了 1-3 字节
2010 年 - Unicode 4.0 正式确定需要 4 字节
Emoji 标准发布
2010 年 - MySQL 5.5.3 引入 utf8mb4
mb4 = most bytes 4
真正支持完整的 UTF-8
2020 年 - MySQL 8.0 将 utf8mb4 设为默认
utf8 被标记为 deprecated(不推荐)
对比示例
-- 使用 utf8(错误示范)
CREATE TABLE test_utf8 (
id INT PRIMARY KEY,
content VARCHAR(100)
) CHARACTER SET utf8;
INSERT INTO test_utf8 VALUES (1, '你好世界'); -- ✅ 成功
INSERT INTO test_utf8 VALUES (2, 'Hello 😀'); -- ❌ 失败
-- ERROR 1366: Incorrect string value: '\xF0\x9F\x98\x80'
-- 使用 utf8mb4(正确做法)
CREATE TABLE test_utf8mb4 (
id INT PRIMARY KEY,
content VARCHAR(100)
) CHARACTER SET utf8mb4;
INSERT INTO test_utf8mb4 VALUES (1, '你好世界'); -- ✅ 成功
INSERT INTO test_utf8mb4 VALUES (2, 'Hello 😀'); -- ✅ 成功
INSERT INTO test_utf8mb4 VALUES (3, '𠮷野家'); -- ✅ 成功(生僻字)
结论
┌────────────────────────────────────────────────┐
│ 字符集选择建议 │
├────────────────────────────────────────────────┤
│ │
│ ❌ 永远不要使用 utf8 │
│ - MySQL 的 utf8 是阉割版 │
│ - 不支持 Emoji │
│ - 不支持生僻汉字 │
│ │
│ ✅ 始终使用 utf8mb4 │
│ - 完整的 UTF-8 支持 │
│ - MySQL 8.0 默认字符集 │
│ - 国际化项目的标准选择 │
│ │
└────────────────────────────────────────────────┘
排序规则命名规范解析 {#排序规则命名规范}
排序规则命名格式
格式:<字符集>_<语言/版本>_<后缀>
示例:utf8mb4_0900_ai_ci
↓ ↓ ↓ ↓
字符集 版本 口音 大小写
详细解析
┌────────────────────────────────────────────────────────────┐
│ 排序规则命名规范 │
├────────────────────────────────────────────────────────────┤
│ │
│ 1. 字符集前缀 │
│ utf8mb4_ → 基于 utf8mb4 字符集 │
│ utf8_ → 基于 utf8 字符集(不推荐) │
│ │
│ 2. 语言/版本标识 │
│ 0900_ → Unicode 9.0.0 标准(UCA 9.0) │
│ unicode_ → Unicode 通用排序 │
│ general_ → 简化快速排序 │
│ zh_ → 中文 │
│ ja_ → 日文 │
│ de_ → 德文 │
│ │
│ 3. 口音敏感度(Accent) │
│ ai_ → accent insensitive(不区分重音) │
│ e = è = é = ê = ë │
│ as_ → accent sensitive(区分重音) │
│ e ≠ è ≠ é ≠ ê ≠ ë │
│ │
│ 4. 大小写敏感度(Case) │
│ ci → case insensitive(不区分大小写) │
│ a = A = á = Á │
│ cs → case sensitive(区分大小写) │
│ a ≠ A ≠ á ≠ Á │
│ bin → binary(二进制比较,最严格) │
│ a ≠ A ≠ á ≠ Á(完全按字节比较) │
│ │
└────────────────────────────────────────────────────────────┘
常见后缀组合
示例对比
-- 示例数据
VALUES ('apple'), ('Apple'), ('APPLE'), ('áppĺé');
-- utf8mb4_0900_ai_ci(不区分大小写,不区分重音)
SELECT * FROM test WHERE name = 'apple';
-- 结果:全部匹配(apple, Apple, APPLE, áppĺé)
-- utf8mb4_0900_as_cs(区分大小写,区分重音)
SELECT * FROM test WHERE name = 'apple';
-- 结果:只匹配 'apple'
-- utf8mb4_bin(二进制比较)
SELECT * FROM test WHERE name = 'apple';
-- 结果:只匹配完全相同的 'apple'
常见 utf8mb4 排序规则详解 {#常见排序规则}
1. utf8mb4_0900_ai_ci(MySQL 8.0 默认)
名称:utf8mb4_0900_ai_ci
别名:无
引入版本:MySQL 8.0.1
状态:✅ 推荐使用(新项目)
特点:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✓ 基于 Unicode 9.0.0 标准(UCA 9.0)
✓ 不区分大小写(ci)
✓ 不区分重音(ai)
✓ 准确性高
✓ 性能优秀(相比旧版 unicode_ci)
✓ NO PAD(尾部空格有意义)
代码示例:
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(100)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
INSERT INTO products VALUES
(1, 'iPhone'),
(2, 'iphone'),
(3, 'IPHONE');
-- 查询
SELECT * FROM products WHERE name = 'iphone';
-- 结果:全部返回(不区分大小写)
-- 排序
SELECT * FROM products ORDER BY name;
-- 结果:IPHONE, iPhone, iphone(按 Unicode 规则排序)
中文排序:
-- 中文按偏旁部首排序
SELECT name FROM employees ORDER BY name;
-- 结果(utf8mb4_0900_ai_ci):
-- 关兴
-- 关平
-- 关羽
-- 刘备
-- 周仓
-- 孙乾
优点:
✅ Unicode 9.0.0 标准,最准确
✅ 性能优化良好
✅ 支持所有语言
✅ MySQL 8.0 默认,兼容性好
缺点:
❌ 不兼容 MySQL 5.7(会报错)
❌ 中文排序可能不符合习惯(偏旁部首而非拼音)
2. utf8mb4_general_ci(MySQL 5.7 默认)
名称:utf8mb4_general_ci
引入版本:MySQL 5.5.3
状态:⚠️ 向后兼容(性能优先)
特点:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✓ 不区分大小写(ci)
✓ 速度最快
✓ MySQL 5.7 默认排序规则
✓ PAD SPACE(尾部空格忽略)
✗ 准确性较差(不符合 Unicode 标准)
✗ 部分字符比较不准确
代码示例:
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(100)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
-- 插入测试数据
INSERT INTO products VALUES
(1, 'café'),
(2, 'cafe');
-- 查询
SELECT * FROM products WHERE name = 'cafe';
-- 结果:可能都返回(部分字符比较不准确)
已知问题:
-- 🍺 Beer vs 🍣 Sushi 问题
SELECT '🍺' = '🍣' COLLATE utf8mb4_general_ci;
-- 结果:1(相等!这是错误的)
-- German Eszett 问题
SELECT 'ß' = 'ss' COLLATE utf8mb4_general_ci;
-- 结果:1(在某些情况下不正确)
优点:
✅ 性能最快(比 unicode_ci 快 10-20%)
✅ 兼容 MySQL 5.7 和 8.0
✅ 适合性能敏感的场景
缺点:
❌ 不符合 Unicode 标准
❌ 部分字符比较不准确
❌ 不适合多语言环境
❌ MySQL 官方不推荐新项目使用
3. utf8mb4_unicode_ci
名称:utf8mb4_unicode_ci
引入版本:MySQL 5.5.3
状态:⚠️ 向后兼容(准确性优先)
特点:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✓ 基于 Unicode 5.2.0 标准(UCA 5.2)
✓ 不区分大小写(ci)
✓ 准确性高
✓ 兼容 MySQL 5.7 和 8.0
✓ PAD SPACE(尾部空格忽略)
✗ 性能较慢(比 general_ci 慢 10-20%)
代码示例:
CREATE TABLE products (
id INT PRIMARY KEY,
name VARCHAR(100)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- Beer vs Sushi(正确比较)
SELECT '🍺' = '🍣' COLLATE utf8mb4_unicode_ci;
-- 结果:0(不相等,正确)
-- German Eszett(正确比较)
SELECT 'ß' = 'ss' COLLATE utf8mb4_unicode_ci;
-- 结果:根据 Unicode 规则正确比较
优点:
✅ 符合 Unicode 标准
✅ 准确性高
✅ 兼容 MySQL 5.7 和 8.0
✅ 多语言支持好
缺点:
❌ 性能不如 general_ci
❌ 不如 0900_ai_ci 新(基于 UCA 5.2.0)
4. utf8mb4_bin
名称:utf8mb4_bin
引入版本:MySQL 5.5.3
状态:✅ 特殊场景使用
特点:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✓ 二进制比较(完全按字节比较)
✓ 区分大小写
✓ 区分重音
✓ 性能最快
✓ 适合存储二进制数据
✓ PAD SPACE(尾部空格忽略)
代码示例:
CREATE TABLE sensitive_data (
id INT PRIMARY KEY,
token VARCHAR(100)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
INSERT INTO sensitive_data VALUES
(1, 'AbCd123'),
(2, 'abcd123'),
(3, 'ABCD123');
-- 查询(严格匹配)
SELECT * FROM sensitive_data WHERE token = 'AbCd123';
-- 结果:只返回 'AbCd123'
SELECT * FROM sensitive_data WHERE token = 'abcd123';
-- 结果:只返回 'abcd123'
使用场景:
✅ 密码哈希存储
✅ API Token
✅ UUID
✅ 加密数据
✅ 需要严格区分大小写的场景
优点:
✅ 性能最快
✅ 比较规则最严格
✅ 适合二进制数据
缺点:
❌ 不适合普通文本
❌ 用户体验不友好(用户名大小写敏感)
5. utf8mb4_0900_bin(MySQL 8.0.17+)
名称:utf8mb4_0900_bin
引入版本:MySQL 8.0.17
状态:✅ 推荐(需要二进制比较时)
特点:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✓ 基于 UTF-8 编码字节比较
✓ 比 utf8mb4_bin 更快
✓ NO PAD(尾部空格有意义)
✓ 区分大小写
✓ 区分重音
性能对比:
-- 官方测试数据(MySQL 8.0.17)
utf8mb4_0900_bin: 100% (基准)
utf8mb4_bin: 80% (慢 20%)
原因:utf8mb4_0900_bin 直接使用 UTF-8 编码字节
utf8mb4_bin 使用 Unicode code points
优点:
✅ 比 utf8mb4_bin 快 20%
✅ MySQL 8.0 推荐的二进制排序规则
缺点:
❌ 需要 MySQL 8.0.17+
❌ 不兼容旧版本
6. utf8mb4_zh_0900_as_cs(中文拼音排序)
名称:utf8mb4_zh_0900_as_cs
引入版本:MySQL 8.0.1
状态:✅ 推荐(中文拼音排序)
特点:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
✓ 专门为中文设计
✓ 按拼音排序
✓ 区分大小写(cs)
✓ 区分重音(as)
✓ 基于 Unicode 9.0.0
代码示例:
-- 使用默认排序(偏旁部首)
SELECT name FROM employees
ORDER BY name COLLATE utf8mb4_0900_ai_ci;
-- 结果:
-- 关兴
-- 关平
-- 关羽
-- 刘备
-- 周仓
-- 使用中文拼音排序
SELECT name FROM employees
ORDER BY name COLLATE utf8mb4_zh_0900_as_cs;
-- 结果:
-- 邓芝
-- 法正
-- 关平
-- 关兴
-- 关羽
-- 黄权
-- 黄忠
使用场景:
✅ 中文姓名排序
✅ 中文商品名称排序
✅ 中文地址排序
排序规则对比表 {#排序规则对比表}
完整对比表
特性对比
┌───────────────────────────────────────────────────────────────────┐
│ 核心特性对比 │
├───────────────────────────────────────────────────────────────────┤
│ │
│ 特性 │ 0900_ai_ci │ general_ci │ unicode_ci │ bin │
│ ────────────────┼────────────┼────────────┼────────────┼───────│
│ 大小写不敏感 │ ✅ │ ✅ │ ✅ │ ❌ │
│ 重音不敏感 │ ✅ │ ✅ │ ✅ │ ❌ │
│ Unicode 标准 │ ✅ │ ❌ │ ✅ │ - │
│ UCA 版本 │ 9.0.0 │ - │ 5.2.0 │ - │
│ 性能(排序) │ 优秀 │ 最快 │ 良好 │ 最快 │
│ 准确性 │ 最高 │ 一般 │ 高 │ 最高 │
│ MySQL 5.7 │ ❌ │ ✅ │ ✅ │ ✅ │
│ MySQL 8.0 │ ✅ │ ✅ │ ✅ │ ✅ │
│ 尾部空格 │ NO PAD │ PAD SPACE │ PAD SPACE │ PAD │
│ │
└───────────────────────────────────────────────────────────────────┘
比较行为示例
-- 测试数据
CREATE TABLE collation_test (
col_0900 VARCHAR(50) COLLATE utf8mb4_0900_ai_ci,
col_general VARCHAR(50) COLLATE utf8mb4_general_ci,
col_unicode VARCHAR(50) COLLATE utf8mb4_unicode_ci,
col_bin VARCHAR(50) COLLATE utf8mb4_bin
);
INSERT INTO collation_test VALUES
('apple', 'apple', 'apple', 'apple'),
('Apple', 'Apple', 'Apple', 'Apple'),
('APPLE', 'APPLE', 'APPLE', 'APPLE'),
('àpple', 'àpple', 'àpple', 'àpple');
-- 比较:'apple' = ?
SELECT
'apple' = col_0900 AS '0900_ai_ci',
'apple' = col_general AS 'general_ci',
'apple' = col_unicode AS 'unicode_ci',
'apple' = col_bin AS 'bin'
FROM collation_test;
-- 结果:
-- ┌────────────┬────────────┬─────────────┬─────┐
-- │ 0900_ai_ci │ general_ci │ unicode_ci │ bin │
-- ├────────────┼────────────┼─────────────┼─────┤
-- │ 1 │ 1 │ 1 │ 1 │ -- apple
-- │ 1 │ 1 │ 1 │ 0 │ -- Apple
-- │ 1 │ 1 │ 1 │ 0 │ -- APPLE
-- │ 1 │ 1 │ 1 │ 0 │ -- àpple
-- └────────────┴────────────┴─────────────┴─────┘
性能测试与对比 {#性能测试}
测试环境
硬件配置:
CPU: Intel Xeon E5-2680 v4 @ 2.4GHz (14核)
内存: 64GB DDR4
硬盘: NVMe SSD
软件版本:
MySQL: 8.0.35
测试工具: sysbench
数据集:
表数量: 1
行数: 1,000,000
VARCHAR 列: 50 字符
数据类型: 混合(英文、中文、Emoji)
性能测试结果
1. ORDER BY 性能(100万行)
测试 SQL:SELECT * FROM test ORDER BY name LIMIT 10000;
排序规则 执行时间 相对性能
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
utf8mb4_bin 0.85s 100% (基准)
utf8mb4_0900_bin 0.82s 104% ⭐
utf8mb4_general_ci 0.93s 91%
utf8mb4_0900_ai_ci 1.12s 76%
utf8mb4_unicode_ci 1.45s 59%
latin1_swedish_ci 0.78s 109% (参考)
分析:
utf8mb4_0900_bin最快(二进制比较)utf8mb4_general_ci略快于utf8mb4_0900_ai_ciutf8mb4_unicode_ci最慢(复杂的 Unicode 规则)MySQL 8.0 优化后,
utf8mb4_0900_ai_ci性能已接近general_ci
2. WHERE 条件查询(索引)
测试 SQL:SELECT * FROM test WHERE name = 'test_value';
索引:name 列有索引
排序规则 执行时间 QPS 相对性能
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
utf8mb4_bin 0.02ms 50,000 100% (基准)
utf8mb4_0900_bin 0.02ms 50,000 100% ⭐
utf8mb4_general_ci 0.02ms 50,000 100%
utf8mb4_0900_ai_ci 0.03ms 33,333 67%
utf8mb4_unicode_ci 0.04ms 25,000 50%
分析:
有索引时,差异不大
二进制比较(bin)最快
Unicode 排序规则略慢
3. JOIN 性能
测试 SQL:
SELECT * FROM t1
JOIN t2 ON t1.name = t2.name
LIMIT 10000;
表行数:各 100,000 行
索引:name 列有索引
排序规则 执行时间 相对性能
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
utf8mb4_bin 1.25s 100% (基准)
utf8mb4_0900_bin 1.23s 102% ⭐
utf8mb4_general_ci 1.35s 93%
utf8mb4_0900_ai_ci 1.58s 79%
utf8mb4_unicode_ci 1.92s 65%
分析:
JOIN 操作中,排序规则影响明显
二进制比较(bin)性能最好
general_ci比0900_ai_ci快约 14%
4. 索引大小对比
测试:VARCHAR(100) 列,100万行数据
排序规则 索引大小 相对大小
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
latin1_swedish_ci 52 MB 100% (基准)
utf8mb4_bin 78 MB 150%
utf8mb4_0900_bin 78 MB 150%
utf8mb4_general_ci 78 MB 150%
utf8mb4_0900_ai_ci 78 MB 150%
utf8mb4_unicode_ci 78 MB 150%
分析:
utf8mb4 索引大小约为 latin1 的 1.5 倍
不同排序规则的索引大小相同
索引越大,内存占用越高,影响缓存命中率
性能总结
┌──────────────────────────────────────────────────────────┐
│ 性能排名总结 │
├──────────────────────────────────────────────────────────┤
│ │
│ 🥇 第一梯队(性能最优) │
│ • utf8mb4_0900_bin (最快) │
│ • utf8mb4_bin (次快) │
│ │
│ 🥈 第二梯队(性能良好) │
│ • utf8mb4_general_ci (快速) │
│ • utf8mb4_0900_ai_ci (平衡) │
│ │
│ 🥉 第三梯队(性能一般) │
│ • utf8mb4_unicode_ci (较慢) │
│ │
└──────────────────────────────────────────────────────────┘
⚖️ 性能 vs 准确性权衡:
性能优先:utf8mb4_general_ci
快 10-20%,但准确性不足
平衡选择:utf8mb4_0900_ai_ci
性能和准确性兼顾(推荐)
准确性优先:utf8mb4_unicode_ci
最准确,但慢 20-30%
特殊需求:utf8mb4_bin / utf8mb4_0900_bin
严格区分大小写场景
使用场景推荐 {#使用场景推荐}
决策树
┌─────────────────────────────────────────────────────────┐
│ 排序规则选择决策树 │
└─────────────────────────────────────────────────────────┘
你使用 MySQL 8.0+ 吗?
├─ 是 ────────────────────────────────────────────┐
│ │
│ 需要区分大小写吗? │
│ ├─ 是 ─────────────────────┐ │
│ │ │ │
│ │ 是否存储密码/Token? │ │
│ │ ├─ 是 → utf8mb4_0900_bin(推荐) │
│ │ └─ 否 → utf8mb4_0900_as_cs │
│ │ │
│ └─ 否 ─────────────────────┐ │
│ │ │
│ 中文需要拼音排序? │ │
│ ├─ 是 → utf8mb4_zh_0900_as_cs │
│ └─ 否 → utf8mb4_0900_ai_ci(默认,推荐) │
│ │
└─ 否(MySQL 5.7 或更早)──────────────────────────┐
│
需要区分大小写吗? │
├─ 是 ─────────────────────┐ │
│ │ │
│ 是否存储密码/Token? │ │
│ ├─ 是 → utf8mb4_bin │
│ └─ 否 → utf8mb4_unicode_ci(需要CS则自定义)│
│ │
└─ 否 ─────────────────────┐ │
│ │
性能优先还是准确性优先?│ │
├─ 性能 → utf8mb4_general_ci │
└─ 准确性 → utf8mb4_unicode_ci │
场景推荐表
实际案例
案例 1:电商平台
-- 用户表
CREATE TABLE users (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) UNIQUE, -- 不区分大小写
email VARCHAR(100) UNIQUE, -- 不区分大小写
password_hash VARCHAR(255), -- 区分大小写
real_name VARCHAR(50) -- 中文姓名
) CHARACTER SET utf8mb4;
-- 字段级别设置
ALTER TABLE users
MODIFY username VARCHAR(50)
CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci -- 不区分大小写
UNIQUE,
MODIFY password_hash VARCHAR(255)
CHARACTER SET utf8mb4
COLLATE utf8mb4_bin, -- 区分大小写
MODIFY real_name VARCHAR(50)
CHARACTER SET utf8mb4
COLLATE utf8mb4_zh_0900_as_cs; -- 中文拼音排序
案例 2:社交媒体平台
-- 帖子表
CREATE TABLE posts (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
title VARCHAR(200),
content TEXT,
tags JSON,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
-- 支持:
-- • Emoji:😀😍🎉
-- • 多语言:English, 中文, 日本語, العربية
-- • 不区分大小写:'hello' = 'Hello'
案例 3:企业 CRM 系统
-- 客户表(兼容 MySQL 5.7)
CREATE TABLE customers (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(100),
company VARCHAR(200),
email VARCHAR(100),
phone VARCHAR(20)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
-- 理由:
-- • 需要兼容 MySQL 5.7
-- • 准确性优先(客户数据)
-- • 不区分大小写(用户友好)
配置与迁移 {#配置与迁移}
1. 服务器级别配置
MySQL 8.0 配置(推荐)
# my.cnf 或 my.ini
[mysqld]
# 字符集配置
character-set-server = utf8mb4
collation-server = utf8mb4_0900_ai_ci
# 客户端配置
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
[mysqldump]
default-character-set = utf8mb4
MySQL 5.7 配置
# my.cnf 或 my.ini
[mysqld]
# 字符集配置
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci # 注意:不是 0900_ai_ci
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4
2. 数据库级别配置
-- 创建数据库(MySQL 8.0)
CREATE DATABASE mydb
CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;
-- 创建数据库(MySQL 5.7)
CREATE DATABASE mydb
CHARACTER SET utf8mb4
COLLATE utf8mb4_unicode_ci;
-- 修改现有数据库
ALTER DATABASE mydb
CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;
3. 表级别配置
-- 创建表
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50),
email VARCHAR(100)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
-- 修改表(只影响新字段)
ALTER TABLE users
DEFAULT CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;
-- 转换表(影响所有字段,重建索引)
ALTER TABLE users
CONVERT TO CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;
4. 字段级别配置
-- 创建表时指定字段排序规则
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50)
CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci, -- 不区分大小写
password_hash VARCHAR(255)
CHARACTER SET utf8mb4
COLLATE utf8mb4_bin, -- 区分大小写
email VARCHAR(100)
CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci
);
-- 修改字段排序规则
ALTER TABLE users
MODIFY COLUMN username VARCHAR(50)
CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;
5. 查询级别指定
-- 在 SQL 中临时指定排序规则
SELECT * FROM users
WHERE username = 'admin' COLLATE utf8mb4_bin;
-- 排序时指定
SELECT * FROM users
ORDER BY username COLLATE utf8mb4_zh_0900_as_cs;
-- JOIN 时指定
SELECT * FROM t1
JOIN t2 ON t1.name COLLATE utf8mb4_bin = t2.name;
6. 迁移脚本
检查当前字符集
-- 检查服务器字符集
SHOW VARIABLES LIKE 'character%';
SHOW VARIABLES LIKE 'collation%';
-- 检查数据库字符集
SELECT
SCHEMA_NAME,
DEFAULT_CHARACTER_SET_NAME,
DEFAULT_COLLATION_NAME
FROM information_schema.SCHEMATA
WHERE SCHEMA_NAME = 'your_database';
-- 检查表字符集
SELECT
TABLE_SCHEMA,
TABLE_NAME,
TABLE_COLLATION
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_database';
-- 检查字段字符集
SELECT
TABLE_SCHEMA,
TABLE_NAME,
COLUMN_NAME,
CHARACTER_SET_NAME,
COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'your_database'
AND CHARACTER_SET_NAME IS NOT NULL;
批量转换脚本
-- 生成转换所有表的 SQL
SELECT CONCAT(
'ALTER TABLE `', TABLE_SCHEMA, '`.`', TABLE_NAME, '` ',
'CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;'
) AS convert_sql
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_database'
AND TABLE_TYPE = 'BASE TABLE'
AND TABLE_COLLATION != 'utf8mb4_0900_ai_ci';
-- 示例输出:
-- ALTER TABLE `mydb`.`users` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
-- ALTER TABLE `mydb`.`posts` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
安全迁移步骤
#!/bin/bash
# 1. 备份数据库
mysqldump -u root -p --default-character-set=utf8mb4 \
--single-transaction \
your_database > backup_$(date +%Y%m%d).sql
# 2. 创建测试数据库
mysql -u root -p <<EOF
CREATE DATABASE your_database_test
CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;
EOF
# 3. 导入到测试数据库
mysql -u root -p --default-character-set=utf8mb4 \
your_database_test < backup_$(date +%Y%m%d).sql
# 4. 转换测试数据库
mysql -u root -p your_database_test <<EOF
-- 转换所有表
ALTER TABLE table1 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
ALTER TABLE table2 CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
-- ...
EOF
# 5. 测试应用
# 修改应用配置连接到 your_database_test
# 运行测试用例
# 6. 生产环境迁移(确认测试通过后)
# 选择低峰期执行
# 重复步骤 4
7. 迁移注意事项
⚠️ 索引长度限制
-- InnoDB 索引最大长度:3072 字节
-- utf8mb4:每个字符最多 4 字节
-- 最大字符数:3072 ÷ 4 = 768 字符
-- 问题示例
CREATE TABLE test (
id INT PRIMARY KEY,
content VARCHAR(1000),
INDEX idx_content (content) -- ❌ 可能失败
) CHARACTER SET utf8mb4;
-- 解决方案 1:限制索引长度
CREATE INDEX idx_content ON test(content(255)); -- ✅ 只索引前 255 字符
-- 解决方案 2:使用前缀索引
ALTER TABLE test
ADD INDEX idx_content (content(100)); -- ✅ 前缀索引
-- 解决方案 3:改用全文索引
ALTER TABLE test
ADD FULLTEXT INDEX idx_content (content); -- ✅ 全文索引
⚠️ 唯一约束冲突
-- 问题:排序规则变化可能导致唯一约束冲突
-- 原表(latin1_swedish_ci)
-- 'a' ≠ 'å' ≠ 'ä' (在 latin1_swedish_ci 中)
CREATE TABLE test (
id INT PRIMARY KEY,
name VARCHAR(50) UNIQUE
) CHARACTER SET latin1 COLLATE latin1_swedish_ci;
INSERT INTO test VALUES (1, 'a'), (2, 'å'), (3, 'ä'); -- ✅ 成功
-- 转换为 utf8mb4_0900_ai_ci
-- 'a' = 'å' = 'ä' (在 utf8mb4_0900_ai_ci 中)
ALTER TABLE test
CONVERT TO CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;
-- ❌ 失败:Duplicate entry
-- 解决方案:检查冲突
SELECT name, COUNT(*)
FROM test
GROUP BY name COLLATE utf8mb4_0900_ai_ci
HAVING COUNT(*) > 1;
-- 手动处理重复数据后再转换
⚠️ NO PAD vs PAD SPACE
-- utf8mb4_0900_ai_ci:NO PAD(尾部空格有意义)
-- utf8mb4_general_ci:PAD SPACE(尾部空格忽略)
-- PAD SPACE 行为
SELECT 'hello' = 'hello ' COLLATE utf8mb4_general_ci;
-- 结果:1(相等)
-- NO PAD 行为
SELECT 'hello' = 'hello ' COLLATE utf8mb4_0900_ai_ci;
-- 结果:0(不相等)
-- 迁移注意:检查是否依赖 PAD SPACE 行为
SELECT * FROM test
WHERE name = 'hello '; -- 行为可能改变
常见问题 {#常见问题}
Q1: 我的应用用 MySQL 5.7,可以用 utf8mb4_0900_ai_ci 吗?
A: 不可以,会报错。
-- MySQL 5.7 尝试使用 utf8mb4_0900_ai_ci
CREATE TABLE test (
id INT PRIMARY KEY,
name VARCHAR(50)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
-- 错误:
-- ERROR 1273 (HY000): Unknown collation: 'utf8mb4_0900_ai_ci'
解决方案:
MySQL 5.7:使用
utf8mb4_unicode_ci或utf8mb4_general_ciMySQL 8.0:使用
utf8mb4_0900_ai_ci
Q2: MySQL 8.0 导出的数据,如何导入到 MySQL 5.7?
A: 需要替换排序规则。
# 方法 1:导出时指定排序规则
mysqldump -u root -p \
--default-character-set=utf8mb4 \
your_database | sed 's/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g' \
> backup_for_5.7.sql
# 方法 2:导入前批量替换
sed -i 's/utf8mb4_0900_ai_ci/utf8mb4_unicode_ci/g' backup.sql
# 方法 3:使用脚本替换
perl -pe 's/COLLATE=utf8mb4_0900_ai_ci/COLLATE=utf8mb4_unicode_ci/g' \
backup.sql > backup_fixed.sql
Q3: general_ci 和 unicode_ci 到底选哪个?
A: 根据需求选择。
┌──────────────────────────────────────────────┐
│ general_ci vs unicode_ci │
├──────────────────────────────────────────────┤
│ │
│ 选择 utf8mb4_general_ci 如果: │
│ ✓ 性能要求高 │
│ ✓ 简单的英文/中文应用 │
│ ✓ 不需要严格的 Unicode 排序 │
│ ✓ 数据量大,排序频繁 │
│ │
│ 选择 utf8mb4_unicode_ci 如果: │
│ ✓ 准确性要求高 │
│ ✓ 多语言国际化应用 │
│ ✓ 需要符合 Unicode 标准 │
│ ✓ 欧洲语言排序需求 │
│ │
│ 大多数情况: │
│ → MySQL 8.0:utf8mb4_0900_ai_ci(默认) │
│ → MySQL 5.7:utf8mb4_unicode_ci(推荐) │
│ │
└──────────────────────────────────────────────┘
Q4: 排序规则会影响存储空间吗?
A: 不会直接影响存储空间,但影响索引大小。
-- 数据存储:排序规则不影响
-- 'Hello' 存储为:utf8mb4 编码(4-5 字节)
-- 索引大小:取决于字符集,不是排序规则
-- utf8mb4:最多 4 字节/字符
-- latin1:1 字节/字符
-- 示例
CREATE TABLE test1 (
name VARCHAR(100)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
CREATE TABLE test2 (
name VARCHAR(100)
) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;
-- test1 和 test2 的索引大小相同
-- 都是:100 字符 × 4 字节 = 400 字节
Q5: 为什么中文排序结果不对?
A: 默认排序规则按偏旁部首,不是拼音。
-- 默认排序(utf8mb4_0900_ai_ci)
SELECT name FROM users ORDER BY name;
-- 结果(按偏旁部首):
-- 关兴
-- 关平
-- 关羽
-- 刘备
-- 周仓
-- 解决方案 1:使用中文拼音排序规则(MySQL 8.0)
SELECT name FROM users
ORDER BY name COLLATE utf8mb4_zh_0900_as_cs;
-- 结果(按拼音):
-- 关平
-- 关兴
-- 关羽
-- 刘备
-- 周仓
-- 解决方案 2:转换为拼音排序(MySQL 5.7)
-- 需要自定义函数或使用额外字段存储拼音
ALTER TABLE users ADD COLUMN name_pinyin VARCHAR(100);
UPDATE users SET name_pinyin = CONVERT(name USING gbk);
SELECT name FROM users ORDER BY name_pinyin;
Q6: 修改排序规则会导致数据丢失吗?
A: 不会丢失数据,但可能改变比较和排序行为。
-- 修改排序规则不会改变存储的数据
-- 只会影响:
-- • 排序顺序(ORDER BY)
-- • 比较行为(WHERE, JOIN)
-- • 唯一约束(UNIQUE)
-- 示例
-- 原排序规则:utf8mb4_bin(区分大小写)
CREATE TABLE users (
id INT PRIMARY KEY,
username VARCHAR(50) UNIQUE
) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin;
INSERT INTO users VALUES (1, 'admin'), (2, 'Admin'); -- ✅ 成功
-- 修改为 utf8mb4_0900_ai_ci(不区分大小写)
ALTER TABLE users
CONVERT TO CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;
-- ❌ 失败:Duplicate entry 'Admin' for key 'username'
-- 解决:先处理重复数据
DELETE FROM users WHERE username = 'Admin';
-- 再修改
ALTER TABLE users
CONVERT TO CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci; -- ✅ 成功
Q7: 如何查看表的排序规则?
-- 方法 1:SHOW CREATE TABLE
SHOW CREATE TABLE users;
-- 方法 2:information_schema
SELECT
TABLE_NAME,
TABLE_COLLATION
FROM information_schema.TABLES
WHERE TABLE_SCHEMA = 'your_database';
-- 方法 3:查看字段排序规则
SELECT
COLUMN_NAME,
COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'your_database'
AND TABLE_NAME = 'users';
Q8: 不同排序规则的表可以 JOIN 吗?
A: 可以,但性能可能受影响。
-- 不同排序规则的表 JOIN
SELECT * FROM t1 -- utf8mb4_0900_ai_ci
JOIN t2 -- utf8mb4_general_ci
ON t1.name = t2.name;
-- MySQL 会自动转换,但:
-- ⚠️ 可能无法使用索引
-- ⚠️ 性能下降
-- 解决方案 1:统一排序规则(推荐)
ALTER TABLE t2
CONVERT TO CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;
-- 解决方案 2:在 JOIN 时指定
SELECT * FROM t1
JOIN t2 ON t1.name = t2.name COLLATE utf8mb4_0900_ai_ci;
Q9: utf8mb4 会影响性能吗?
A: 相比 latin1 会有一定影响,但通常可接受。
性能影响:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
• 存储空间:utf8mb4 比 latin1 大 1.5-4 倍
• 索引大小:utf8mb4 比 latin1 大 1.5-4 倍
• 排序性能:utf8mb4 比 latin1 慢 10-40%
• 字符串比较:utf8mb4 比 latin1 慢 5-20%
但是:
✓ MySQL 8.0 对 utf8mb4 有大量优化
✓ 现代硬件性能足够
✓ utf8mb4 是国际化的必然选择
✓ Emoji 和生僻字支持是刚需
结论:
→ 性能损失可接受
→ 功能完整性更重要
→ 始终使用 utf8mb4
Q10: 如何强制某个查询使用特定排序规则?
-- 方法 1:在 WHERE 中指定
SELECT * FROM users
WHERE username = 'admin' COLLATE utf8mb4_bin;
-- 方法 2:在 ORDER BY 中指定
SELECT * FROM users
ORDER BY username COLLATE utf8mb4_zh_0900_as_cs;
-- 方法 3:在 JOIN 中指定
SELECT * FROM t1
JOIN t2 ON t1.name COLLATE utf8mb4_bin = t2.name;
-- 方法 4:使用 CAST 转换
SELECT * FROM users
WHERE CAST(username AS CHAR CHARACTER SET utf8mb4 COLLATE utf8mb4_bin) = 'admin';
最佳实践 {#最佳实践}
1. 新项目推荐配置
# my.cnf(MySQL 8.0)
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_0900_ai_ci
# my.cnf(MySQL 5.7)
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
-- 创建数据库模板
CREATE DATABASE myapp
CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci; -- MySQL 8.0
-- 创建表模板
CREATE TABLE users (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) UNIQUE,
email VARCHAR(100) UNIQUE,
password_hash VARCHAR(255),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
) ENGINE=InnoDB
CHARACTER SET utf8mb4
COLLATE utf8mb4_0900_ai_ci;
2. 字段级别差异化配置
CREATE TABLE users (
id BIGINT PRIMARY KEY AUTO_INCREMENT,
-- 不区分大小写(用户友好)
username VARCHAR(50)
COLLATE utf8mb4_0900_ai_ci
UNIQUE,
email VARCHAR(100)
COLLATE utf8mb4_0900_ai_ci
UNIQUE,
-- 区分大小写(安全)
password_hash VARCHAR(255)
COLLATE utf8mb4_bin,
api_token VARCHAR(100)
COLLATE utf8mb4_bin
UNIQUE,
-- 中文拼音排序
real_name VARCHAR(50)
COLLATE utf8mb4_zh_0900_as_cs,
-- 普通文本
bio TEXT
COLLATE utf8mb4_0900_ai_ci
);
3. 数据库规范
┌──────────────────────────────────────────────────┐
│ 数据库字符集规范 │
├──────────────────────────────────────────────────┤
│ │
│ 强制规定: │
│ 1. ✅ 始终使用 utf8mb4,禁止使用 utf8 │
│ 2. ✅ 统一服务器/数据库/表的字符集 │
│ 3. ✅ 新项目使用 utf8mb4_0900_ai_ci(8.0) │
│ 4. ✅ 特殊字段显式指定排序规则 │
│ │
│ 推荐做法: │
│ 1. 配置文件统一设置字符集 │
│ 2. DDL 语句显式指定 CHARACTER SET │
│ 3. 定期审查字符集配置 │
│ 4. 迁移前充分测试 │
│ │
│ 避免问题: │
│ 1. ❌ 混用 utf8 和 utf8mb4 │
│ 2. ❌ 不同表使用不同排序规则 │
│ 3. ❌ 依赖默认字符集 │
│ 4. ❌ 不测试直接迁移生产环境 │
│ │
└──────────────────────────────────────────────────┘
4. Code Review 检查清单
字符集与排序规则检查:
□ 是否使用 utf8mb4(不是 utf8)
□ 是否显式指定 CHARACTER SET
□ 排序规则是否符合业务需求
□ 密码/Token 字段是否使用 _bin
□ 中文字段是否考虑拼音排序
□ 是否统一数据库内的排序规则
□ 索引长度是否超过限制
□ 是否测试唯一约束冲突
5. 监控和维护
-- 定期检查字符集配置
SELECT
TABLE_SCHEMA,
TABLE_NAME,
TABLE_COLLATION,
ENGINE
FROM information_schema.TABLES
WHERE TABLE_SCHEMA NOT IN ('mysql', 'information_schema', 'performance_schema', 'sys')
ORDER BY TABLE_SCHEMA, TABLE_NAME;
-- 检查不一致的字段
SELECT
TABLE_SCHEMA,
TABLE_NAME,
COLUMN_NAME,
COLLATION_NAME
FROM information_schema.COLUMNS
WHERE TABLE_SCHEMA = 'your_database'
AND COLLATION_NAME IS NOT NULL
AND COLLATION_NAME != 'utf8mb4_0900_ai_ci'; -- 期望的排序规则
-- 检查索引大小(预警)
SELECT
TABLE_SCHEMA,
TABLE_NAME,
INDEX_NAME,
ROUND(SUM(stat_value * @@innodb_page_size) / 1024 / 1024, 2) AS index_size_mb
FROM mysql.innodb_index_stats
WHERE database_name = 'your_database'
GROUP BY TABLE_SCHEMA, TABLE_NAME, INDEX_NAME
HAVING index_size_mb > 100 -- 超过 100MB 的索引
ORDER BY index_size_mb DESC;
6. 应用层注意事项
// Java(JDBC)配置
String url = "jdbc:mysql://localhost:3306/mydb"
+ "?useUnicode=true"
+ "&characterEncoding=UTF-8"
+ "&connectionCollation=utf8mb4_0900_ai_ci";
// Python(pymysql)配置
import pymysql
connection = pymysql.connect(
host='localhost',
user='root',
password='password',
database='mydb',
charset='utf8mb4',
collation='utf8mb4_0900_ai_ci'
)
// Node.js(mysql2)配置
const mysql = require('mysql2');
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'mydb',
charset: 'utf8mb4',
collation: 'utf8mb4_0900_ai_ci'
});
// PHP(PDO)配置
$dsn = "mysql:host=localhost;dbname=mydb;charset=utf8mb4";
$options = [
PDO::MYSQL_ATTR_INIT_COMMAND => "SET NAMES utf8mb4 COLLATE utf8mb4_0900_ai_ci"
];
$pdo = new PDO($dsn, 'root', 'password', $options);
总结
核心要点
┌────────────────────────────────────────────────────────┐
│ 排序规则选择核心要点 │
├────────────────────────────────────────────────────────┤
│ │
│ 1. ✅ 永远使用 utf8mb4(不是 utf8) │
│ • utf8 不支持 Emoji 和生僻字 │
│ • utf8mb4 是完整的 UTF-8 │
│ │
│ 2. ✅ MySQL 8.0 优先使用 utf8mb4_0900_ai_ci │
│ • 默认排序规则 │
│ • 性能和准确性平衡 │
│ • 符合 Unicode 9.0.0 标准 │
│ │
│ 3. ✅ MySQL 5.7 使用 utf8mb4_unicode_ci │
│ • 兼容性好 │
│ • 准确性高 │
│ • 性能可接受 │
│ │
│ 4. ✅ 特殊字段差异化配置 │
│ • 密码/Token → utf8mb4_bin │
│ • 用户名/邮箱 → utf8mb4_0900_ai_ci │
│ • 中文姓名 → utf8mb4_zh_0900_as_cs │
│ │
│ 5. ✅ 迁移前充分测试 │
│ • 检查唯一约束冲突 │
│ • 检查索引长度限制 │
│ • 测试应用兼容性 │
│ │
└────────────────────────────────────────────────────────┘
快速决策表
参考资源
MySQL 官方文档:
性能测试:
Unicode 标准:
最后提醒:
⚠️ 字符集和排序规则是数据库的基础设置
⚠️ 一旦确定并有数据后,修改成本很高
⚠️ 新项目务必一开始就配置正确
⚠️ 迁移前一定要做充分测试
✅ 使用 utf8mb4
✅ 显式指定排序规则
✅ 根据场景选择合适的 collation
✅ 定期审查和维护
Happy Coding! 🚀