字符集与排序规则
约 977 字大约 3 分钟
布欧-Lewyon
2026-05-15
首页 › MySQL › 高级特性(在新窗口打开) › 字符集与排序规则
字符集(Character Set)决定字符如何编码为字节,排序规则(Collation)决定字符比较和排序的顺序。选择错误会导致乱码、排序异常、甚至索引失效。
字符集基础
常用字符集
| 字符集 | 字节/字符 | 说明 |
|---|---|---|
latin1 | 1 字节 | 西欧语言,不支持中文 |
utf8 | 1~3 字节 | MySQL 的 utf8 是阉割版(最多 3 字节),不推荐 |
utf8mb4 | 1~4 字节 | 真正的 UTF-8,支持 emoji 和生僻字,推荐 |
gbk | 1~2 字节 | 中文双字节编码 |
utf8 vs utf8mb4
-- utf8 无法存储 4 字节字符
CREATE TABLE bad (
content VARCHAR(100) CHARACTER SET utf8
);
INSERT INTO bad VALUES ('😊'); -- ERROR: Incorrect string value
-- utf8mb4 可以
CREATE TABLE good (
content VARCHAR(100) CHARACTER SET utf8mb4
);
INSERT INTO good VALUES ('😊'); -- 成功硬性建议:MySQL 8.0 以上始终使用
utf8mb4,不要用utf8。
排序规则
排序规则是字符集的属性,决定字符如何比较和排序。
常用 Collation
-- 查看字符集支持的排序规则
SHOW COLLATION WHERE Charset = 'utf8mb4';
-- utf8mb4_general_ci ← 早期默认,速度优先
-- utf8mb4_unicode_ci ← 准确排序,支持更多语言
-- utf8mb4_0900_ai_ci ← MySQL 8.0 默认,基于 Unicode 9.0| Collation | 默认版本 | 特点 |
|---|---|---|
utf8mb4_general_ci | 5.x/5.7 | 速度略快,但排序不够精确 |
utf8mb4_unicode_ci | 5.x/5.7 | 排序准确,支持扩展字符 |
utf8mb4_0900_ai_ci | 8.0 | 基于 Unicode 9.0,ai=口音不敏感,ci=大小写不敏感 |
后缀含义:
| 后缀 | 含义 |
|---|---|
_ci | Case Insensitive(大小写不敏感) |
_cs | Case Sensitive(大小写敏感) |
_bin | 二进制比较(最严格,按字节值) |
_ai | Accent Insensitive(口音不敏感) |
_as | Accent Sensitive(口音敏感) |
设置字符集
设置层级
MySQL 的字符集设置分为四个层级:
-- 1. 服务器级
SHOW VARIABLES LIKE 'character_set_server';
-- SET GLOBAL character_set_server = utf8mb4;
-- 2. 数据库级
CREATE DATABASE demo CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
-- 3. 表级
CREATE TABLE user (...) ENGINE=InnoDB
DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
-- 4. 列级
CREATE TABLE t (
name VARCHAR(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_bin
);连接字符集
客户端与服务器通信时,涉及三个字符集变量:
-- 客户端发送的 SQL 编码
SET character_set_client = utf8mb4;
-- 服务器接收后转换为此编码处理
SET character_set_connection = utf8mb4;
-- 服务器返回结果的编码
SET character_set_results = utf8mb4;
-- 一键设置:以上三个统一
SET NAMES utf8mb4;乱码排查流程:
字符集对性能的影响
utf8mb4比latin1占用更多存储空间,索引更大。- 列使用不同类型时可以导致无法使用索引(隐式转换)。
_bin排序规则比_ci更快,因为无需做大小写转换。
-- 隐式转换导致索引失效
CREATE TABLE user (
name VARCHAR(50) CHARACTER SET utf8mb4
);
CREATE INDEX idx_name ON user(name);
-- ❌ 使用 different charset 的字符串对比
SELECT * FROM user WHERE name = '张三'; -- 正常使用索引
-- 但若 name 是 utf8mb4_bin,比较时用了 utf8mb4_general_ci,可能导致类型转换最佳实践
# my.cnf 推荐配置(MySQL 8.0)
[mysqld]
character-set-server = utf8mb4
collation-server = utf8mb4_0900_ai_ci
[client]
default-character-set = utf8mb4
[mysql]
default-character-set = utf8mb4-- 数据库、表都显式指定
CREATE DATABASE mydb CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
CREATE TABLE mytable (
...
) DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
-- 应用连接后执行
SET NAMES utf8mb4;小结
- MySQL 的
utf8是阉割版(最多 3 字节),始终用utf8mb4。 - 排序规则
_ci大小写不敏感(默认),_bin二进制比较最严,_cs大小写敏感。 - MySQL 8.0 默认
utf8mb4_0900_ai_ci,兼容性最佳。 - 字符集设置分四个层级:服务器、库、表、列,下层继承上层。
- 连接字符集
SET NAMES utf8mb4防止乱码。 - 不同字符集的列对比可能导致索引失效。
