📘 第三章:字符集和比较规则------读书笔记
MySQL如何处理多语言文本数据 和文本排序比较。数据从存储到传输、比较的全过程编码逻辑,是解决"乱码"问题和优化文本查询性能的理论基础。
🎯 本章核心:解决两个问题
-
存储问题(字符集) :一个字符(如'我'、'A'、'🎉')在计算机中到底用什么二进制代码表示?
-
比较问题(比较规则):如何判断两个字符(如'a'和'A')是否"相等"?谁大谁小?
📖 详细内容拆解
3.1 字符集和比较规则简介
-
字符集 (Charset) = 字符范围 + 编码规则
-
定义了哪些字符可以被认可(如ASCII只有128个,GBK有汉字,UTF-8几乎包含所有)。
-
定义了每个字符对应的唯一二进制编码(如'A' -> 0x41)。
-
-
比较规则 (Collation) = 字符集的"排序规则"
-
决定了字符如何比较大小和排序。
-
同一字符集可以有多个比较规则(如
utf8_general_ci不区分大小写,utf8_bin按二进制严格比较)。
-
3.2 MySQL中字符集
-
区别 :MySQL中的
utf8其实是utf8mb3(最多3字节/字符),而utf8mb4才是真正的UTF-8(支持4字节,如表情符号)。 -
现代应用一律使用
utf8mb4。 -
查看字符集支持项的sql语句:
SHOW CHARSET; -- 查看所有字符集及其默认比较规则 SHOW COLLATION LIKE 'utf8mb4%'; -- 查看特定字符集的所有比较规则
3.3 字符集和比较规则的应用(四个层级)
规则:下级未指定时,自动继承上级的设定。
| 层级 | 说明 | 关键系统变量/语法 |
|---|---|---|
| 1. 服务器级 | MySQL实例的默认设置 | character_set_server, collation_server |
| 2. 数据库级 | 创建数据库时可指定 | CREATE DATABASE ... CHAR SET ... COLLATE ... |
| 3. 表级 | 创建表时可指定,继承数据库 | CREATE TABLE ... CHAR SET ... COLLATE ... |
| 4. 列级 | 可为列单独指定,继承表 | 列名 VARCHAR(100) CHAR SET ... COLLATE ... |
优先级从高到低 :
① 列级 > ② 表级 > ③ 数据库级 > ④ 服务器级
修改规则:只修改字符集,比较规则会自动变为新字符集的默认规则;反之亦然。
3.3.2 客户端与服务器通信中的字符集转换(⭐)
这是"乱码"产生的根源。一次简单的查询,数据可能经历多次编解码转换👇:
比如一次数据它的链路历程可能是这样的:
键盘输入 → 客户端编码 → 网络包 → 服务器"认为"的编码 → 连接字符集 → 存储字符集 → 返回字符集 → 终端显示
三个关键会话变量控制此流程:
-
character_set_client:服务器认为客户端发送来的SQL语句是什么编码。 -
character_set_connection:服务器将接收到的语句转换为何种编码进行处理(与字符串字面量比较相关)。 -
character_set_results:服务器将结果集(包括数据、字段名等)转换为何种编码发回客户端。
一键设置 :SET NAMES 'charset_name'; 命令同时修改上述三个变量,通常用于确保连接使用统一的字符集,是解决乱码的常用方法。
3.3.3 比较规则的应用
-
影响
ORDER BY、GROUP BY、DISTINCT、WHERE条件比较等所有涉及字符比较的操作。 -
示例 :
col列使用utf8mb4_general_ci(不区分大小写)排序时,'a'和'A'会被视为相同并排在一起;若使用utf8mb4_bin,则会被区分开。
💎 本章核心总结与最佳实践
1. 概念关系图
字符集 (Charset)
|
|--- 包含多种 ---> 比较规则 (Collation)
| |
| |--- _ci: 不区分大小写
| |--- _cs: 区分大小写
| |--- _bin: 二进制比较
| ci=case insensitive 不区分大小写
cs=case sensitive 区分大小写
bin=binary 按编码值二进制比
|
|
|--- 常见种类 ---> utf8mb4 (推荐), gbk, latin1
2. 配置黄金法则
-
统一 :服务器、数据库、表、连接字符集保持一致(都用
utf8mb4),拒绝乱码。 -
连接即设 :在客户端程序连接后,立即执行
SET NAMES 'utf8mb4';(或配置连接参数),确保通信编码正确。 -
列慎指定 :除非有特殊需求(如某列必须用
latin1存储老数据),否则不需在列级指定,继承表设置即可。
3. 故障排查思路
如果出现乱码或排序不符合预期时,按以下顺序检查:
-
客户端发送的真实编码是什么?(代码文件编码、终端编码)
-
连接层的三个变量(
client/connection/results)设置是否正确?(使用SHOW VARIABLES LIKE 'character_set%';查看) -
目标表/列的字符集和比较规则是什么?(使用
SHOW CREATE TABLE 表名;查看)
4. 重要提醒
-
VARCHAR(100)中的100指的是字符数 ,而非字节数。在utf8mb4下,最多可存储400字节。 -
修改已有数据的列的字符集可能失败(如果新字符集无法表示原有数据)。
-
选择
_ci比较规则能提高模糊匹配的友好度,但需要确保业务逻辑允许。