读书笔记之MySQL的字符集与比较规则小读

📘 第三章:字符集和比较规则------读书笔记

MySQL如何处理多语言文本数据文本排序比较。数据从存储到传输、比较的全过程编码逻辑,是解决"乱码"问题和优化文本查询性能的理论基础。


🎯 本章核心:解决两个问题

  1. 存储问题(字符集) :一个字符(如'我'、'A'、'🎉')在计算机中到底用什么二进制代码表示?

  2. 比较问题(比较规则):如何判断两个字符(如'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 客户端与服务器通信中的字符集转换(⭐)

这是"乱码"产生的根源。一次简单的查询,数据可能经历多次编解码转换👇:

比如一次数据它的链路历程可能是这样的:
键盘输入 → 客户端编码 → 网络包 → 服务器"认为"的编码 → 连接字符集 → 存储字符集 → 返回字符集 → 终端显示

三个关键会话变量控制此流程

  1. character_set_client服务器认为客户端发送来的SQL语句是什么编码。

  2. character_set_connection:服务器将接收到的语句转换为何种编码进行处理(与字符串字面量比较相关)。

  3. character_set_results:服务器将结果集(包括数据、字段名等)转换为何种编码发回客户端。

一键设置SET NAMES 'charset_name'; 命令同时修改上述三个变量,通常用于确保连接使用统一的字符集,是解决乱码的常用方法。

3.3.3 比较规则的应用

  • 影响 ORDER BYGROUP BYDISTINCTWHERE 条件比较等所有涉及字符比较的操作。

  • 示例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. 故障排查思路

如果出现乱码或排序不符合预期时,按以下顺序检查:

  1. 客户端发送的真实编码是什么?(代码文件编码、终端编码)

  2. 连接层的三个变量(client/connection/results)设置是否正确?(使用 SHOW VARIABLES LIKE 'character_set%'; 查看)

  3. 目标表/列的字符集和比较规则是什么?(使用 SHOW CREATE TABLE 表名; 查看)

4. 重要提醒

  • VARCHAR(100) 中的 100 指的是字符数 ,而非字节数。在utf8mb4下,最多可存储400字节。

  • 修改已有数据的列的字符集可能失败(如果新字符集无法表示原有数据)。

  • 选择_ci比较规则能提高模糊匹配的友好度,但需要确保业务逻辑允许。

相关推荐
点云SLAM2 小时前
BOOS库中Graph模块boost::edge_reverse_t和boost::vertex_color_t解读
数据库·edge·图论·bfs·dfs/拓扑排序·boost库、
尽兴-2 小时前
《深入剖析:全面理解 MySQL 的架构设计》
数据库·mysql·数据库架构设计·理解mysql架构
在风中的意志2 小时前
[数据库SQL] [leetcode] 2388. 将表中的空值更改为前一个值
数据库·sql·leetcode
梦幻通灵3 小时前
Mysql字段判空实用技巧
android·数据库·mysql
酸菜牛肉汤面4 小时前
23、varchar与char的区别
数据库
AI题库4 小时前
PostgreSQL 18 从新手到大师:实战指南 - 2.5 Serverless PostgreSQL
数据库·postgresql·serverless
IT技术分享社区5 小时前
数据库实战:MySQL多表更新JOIN操作的底层原理与性能调优指南
数据库·mysql·程序员
廋到被风吹走5 小时前
【数据库】【Oracle】分区表与大表设计
数据库·oracle
UrSpecial5 小时前
InnoDB存储引擎
数据库·mysql
gjc5926 小时前
MySQL隐蔽 BUG:组合条件查询无故返回空集?深度排查与规避方案
android·数据库·mysql·bug