从根上理解 MySQL 的字符集和比较规则

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 字符集和比较规则是MySQL的很重要基础知识,让我们来从根上认识和掌握它们。

字符集

抽象的描述某个字符范围的编码规则(charset),比如ASCII、GBK、UTF8等。

编码:把一个字符映射成一个二进制数据的过程
解码:将一个二进制数据映射成一个字符的过程

比较规则

是针对某个字符集中的字符比较大小的一种规则(collation),比如gbk_chinese_ci、utf8_general_ci等。

一些重要的字符集

ASCII

一共128个字符,包括空格、标点符号、数字、大小写字母和一些不可见字符

1个字节编码一个字符

例如:L
01001100(二进制)
0x4c(十六进制)
76(十进制)

ISO 8859-1

一共256个字符,在ASCII基础扩增128个西欧常用字符

1个字节编码一个字符

别名又叫 Latin1

GB2312

收录汉字以及拉丁字母、希腊字母、日文字母、俄语字母,兼容ASCII

汉字6763个,其它文字符号682个

1~2个字节编码一个字符

编码规则:变长编码方式(表示一个字符需要的字节数可能不同)
1. 如果该字符在ASCII范围内,则采用1字节编码1个字符
2. 否则采用2个字节编码1个字符
例如:i你
01101001 1100010011100011(二进制)
0x69 CE3(十六进制)
105 19227(十进制)

GBK

对GB2312进行扩充,兼容GB2312

1~2个字节编码一个字符

例如:'我'
1100111011010010(二进制)
CE‌D2(十六进制)

UTF8

收录地球上能想到的所有字符,而且还在不断扩充,兼容ASCII

变长编码方式,编码1个字符需要1~4个字节

例如:
'L'
01001100(二进制)
0x4C(十六进制)

'我'
111001101000100010010001(二进制)
0xE6‌88‌91(十六进制)

MySQL中支持的字符集和排序规则

utf8和utf8mb4

utf8:utf8mb3 阉割过的utf8字符集,只使用1~3个字节编码字符。(默认)

utf8mb4:正宗的utf8字符集,使用1~4个字节编码字符。(可以存储emoji表情)

字符集的查看

SHOW (CHARACTER SET|CHARSET) [LIKE 匹配的模式];
mysql> show character set;
+----------+---------------------------------+---------------------+--------+
| Charset  | Description                     | Default collation   | Maxlen |
+----------+---------------------------------+---------------------+--------+
| big5     | Big5 Traditional Chinese        | big5_chinese_ci     |      2 |
| dec8     | DEC West European               | dec8_swedish_ci     |      1 |
| cp850    | DOS West European               | cp850_general_ci    |      1 |
| hp8      | HP West European                | hp8_english_ci      |      1 |
| koi8r    | KOI8-R Relcom Russian           | koi8r_general_ci    |      1 |
| latin1   | cp1252 West European            | latin1_swedish_ci   |      1 |
| latin2   | ISO 8859-2 Central European     | latin2_general_ci   |      1 |
| swe7     | 7bit Swedish                    | swe7_swedish_ci     |      1 |
| ascii    | US ASCII                        | ascii_general_ci    |      1 |
| ujis     | EUC-JP Japanese                 | ujis_japanese_ci    |      3 |
| sjis     | Shift-JIS Japanese              | sjis_japanese_ci    |      2 |
| hebrew   | ISO 8859-8 Hebrew               | hebrew_general_ci   |      1 |
| tis620   | TIS620 Thai                     | tis620_thai_ci      |      1 |
| euckr    | EUC-KR Korean                   | euckr_korean_ci     |      2 |
| koi8u    | KOI8-U Ukrainian                | koi8u_general_ci    |      1 |
| gb2312   | GB2312 Simplified Chinese       | gb2312_chinese_ci   |      2 |
| greek    | ISO 8859-7 Greek                | greek_general_ci    |      1 |
| cp1250   | Windows Central European        | cp1250_general_ci   |      1 |
| gbk      | GBK Simplified Chinese          | gbk_chinese_ci      |      2 |
| latin5   | ISO 8859-9 Turkish              | latin5_turkish_ci   |      1 |
| armscii8 | ARMSCII-8 Armenian              | armscii8_general_ci |      1 |
| utf8     | UTF-8 Unicode                   | utf8_general_ci     |      3 |
| ucs2     | UCS-2 Unicode                   | ucs2_general_ci     |      2 |
| cp866    | DOS Russian                     | cp866_general_ci    |      1 |
| keybcs2  | DOS Kamenicky Czech-Slovak      | keybcs2_general_ci  |      1 |
| macce    | Mac Central European            | macce_general_ci    |      1 |
| macroman | Mac West European               | macroman_general_ci |      1 |
| cp852    | DOS Central European            | cp852_general_ci    |      1 |
| latin7   | ISO 8859-13 Baltic              | latin7_general_ci   |      1 |
| utf8mb4  | UTF-8 Unicode                   | utf8mb4_general_ci  |      4 |
| cp1251   | Windows Cyrillic                | cp1251_general_ci   |      1 |
| utf16    | UTF-16 Unicode                  | utf16_general_ci    |      4 |
| utf16le  | UTF-16LE Unicode                | utf16le_general_ci  |      4 |
| cp1256   | Windows Arabic                  | cp1256_general_ci   |      1 |
| cp1257   | Windows Baltic                  | cp1257_general_ci   |      1 |
| utf32    | UTF-32 Unicode                  | utf32_general_ci    |      4 |
| binary   | Binary pseudo charset           | binary              |      1 |
| geostd8  | GEOSTD8 Georgian                | geostd8_general_ci  |      1 |
| cp932    | SJIS for Windows Japanese       | cp932_japanese_ci   |      2 |
| eucjpms  | UJIS for Windows Japanese       | eucjpms_japanese_ci |      3 |
| gb18030  | China National Standard GB18030 | gb18030_chinese_ci  |      4 |
+----------+---------------------------------+---------------------+--------+
41 rows in set (0.00 sec)

比较规则的查看

SHOW COLLATION [LIKE 匹配的模式];
mysql> show collation like 'utf8%';
+--------------------------+---------+-----+---------+----------+---------+
| Collation                | Charset | Id  | Default | Compiled | Sortlen |
+--------------------------+---------+-----+---------+----------+---------+
| utf8_general_ci          | utf8    |  33 | Yes     | Yes      |       1 |
| utf8_bin                 | utf8    |  83 |         | Yes      |       1 |
| utf8_unicode_ci          | utf8    | 192 |         | Yes      |       8 |
| utf8_icelandic_ci        | utf8    | 193 |         | Yes      |       8 |
| utf8_latvian_ci          | utf8    | 194 |         | Yes      |       8 |
| utf8_romanian_ci         | utf8    | 195 |         | Yes      |       8 |
| utf8_slovenian_ci        | utf8    | 196 |         | Yes      |       8 |
| utf8_polish_ci           | utf8    | 197 |         | Yes      |       8 |
| utf8_estonian_ci         | utf8    | 198 |         | Yes      |       8 |
| utf8_spanish_ci          | utf8    | 199 |         | Yes      |       8 |
| utf8_swedish_ci          | utf8    | 200 |         | Yes      |       8 |
| utf8_turkish_ci          | utf8    | 201 |         | Yes      |       8 |
| utf8_czech_ci            | utf8    | 202 |         | Yes      |       8 |
| utf8_danish_ci           | utf8    | 203 |         | Yes      |       8 |
| utf8_lithuanian_ci       | utf8    | 204 |         | Yes      |       8 |
| utf8_slovak_ci           | utf8    | 205 |         | Yes      |       8 |
| utf8_spanish2_ci         | utf8    | 206 |         | Yes      |       8 |
| utf8_roman_ci            | utf8    | 207 |         | Yes      |       8 |
| utf8_persian_ci          | utf8    | 208 |         | Yes      |       8 |
| utf8_esperanto_ci        | utf8    | 209 |         | Yes      |       8 |
| utf8_hungarian_ci        | utf8    | 210 |         | Yes      |       8 |
| utf8_sinhala_ci          | utf8    | 211 |         | Yes      |       8 |
| utf8_german2_ci          | utf8    | 212 |         | Yes      |       8 |
| utf8_croatian_ci         | utf8    | 213 |         | Yes      |       8 |
| utf8_unicode_520_ci      | utf8    | 214 |         | Yes      |       8 |
| utf8_vietnamese_ci       | utf8    | 215 |         | Yes      |       8 |
| utf8_general_mysql500_ci | utf8    | 223 |         | Yes      |       1 |
| utf8mb4_general_ci       | utf8mb4 |  45 | Yes     | Yes      |       1 |
| utf8mb4_bin              | utf8mb4 |  46 |         | Yes      |       1 |
| utf8mb4_unicode_ci       | utf8mb4 | 224 |         | Yes      |       8 |
| utf8mb4_icelandic_ci     | utf8mb4 | 225 |         | Yes      |       8 |
| utf8mb4_latvian_ci       | utf8mb4 | 226 |         | Yes      |       8 |
| utf8mb4_romanian_ci      | utf8mb4 | 227 |         | Yes      |       8 |
| utf8mb4_slovenian_ci     | utf8mb4 | 228 |         | Yes      |       8 |
| utf8mb4_polish_ci        | utf8mb4 | 229 |         | Yes      |       8 |
| utf8mb4_estonian_ci      | utf8mb4 | 230 |         | Yes      |       8 |
| utf8mb4_spanish_ci       | utf8mb4 | 231 |         | Yes      |       8 |
| utf8mb4_swedish_ci       | utf8mb4 | 232 |         | Yes      |       8 |
| utf8mb4_turkish_ci       | utf8mb4 | 233 |         | Yes      |       8 |
| utf8mb4_czech_ci         | utf8mb4 | 234 |         | Yes      |       8 |
| utf8mb4_danish_ci        | utf8mb4 | 235 |         | Yes      |       8 |
| utf8mb4_lithuanian_ci    | utf8mb4 | 236 |         | Yes      |       8 |
| utf8mb4_slovak_ci        | utf8mb4 | 237 |         | Yes      |       8 |
| utf8mb4_spanish2_ci      | utf8mb4 | 238 |         | Yes      |       8 |
| utf8mb4_roman_ci         | utf8mb4 | 239 |         | Yes      |       8 |
| utf8mb4_persian_ci       | utf8mb4 | 240 |         | Yes      |       8 |
| utf8mb4_esperanto_ci     | utf8mb4 | 241 |         | Yes      |       8 |
| utf8mb4_hungarian_ci     | utf8mb4 | 242 |         | Yes      |       8 |
| utf8mb4_sinhala_ci       | utf8mb4 | 243 |         | Yes      |       8 |
| utf8mb4_german2_ci       | utf8mb4 | 244 |         | Yes      |       8 |
| utf8mb4_croatian_ci      | utf8mb4 | 245 |         | Yes      |       8 |
| utf8mb4_unicode_520_ci   | utf8mb4 | 246 |         | Yes      |       8 |
| utf8mb4_vietnamese_ci    | utf8mb4 | 247 |         | Yes      |       8 |
+--------------------------+---------+-----+---------+----------+---------+
53 rows in set (0.00 sec)
后缀 英文解释 描述
_ai accent insensitive 不区分重音
_as     accent sensitive     区分重音   
_ci case insensitive 不区分大小写
_cs     case sensitive     区分大小写   
_bin binary 以二进制方式比较

后边紧跟着该比较规则主要作用于哪种语言,比如utf8_polish_ci表示以波兰语的规则比较,utf8_spanish_ci是以西班牙语的规则比较,utf8_general_ci是一种通用的比较规则。

字符集和比较规则的应用

服务器级别

查看

SHOW VARIABLES LIKE 'character_set_server';//服务器级别字符集
SHOW VARIABLES LIKE 'collation_server';//服务器级别比较规则
mysql> show variables like 'character_set_server';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| character_set_server | gbk   |
+----------------------+-------+

mysql> show variables like 'collation_server';
+------------------+----------------+
| Variable_name | Value |
+------------------+----------------+
| collation_server | gbk_chinese_ci |
+------------------+----------------+

设置

通过配置文件永久设置(当然也可以通过命令行进行当前会话设置)
[server] 
character_set_server=gbk 
collation_server=gbk_chinese_ci

数据库级别

查看

use 数据库;//需先选择对应的数据库
SHOW VARIABLES LIKE 'character_set_database';//数据库级别的字符集
SHOW VARIABLES LIKE 'collation_database';//数据库级别的比较规则
mysql> use school;
Database changed
mysql> show variables like 'character_set_database';
+------------------------+--------+
| Variable_name          | Value  |
+------------------------+--------+
| character_set_database | latin1 |
+------------------------+--------+

mysql> show variables like 'collation_database';
+--------------------+-------------------+
| Variable_name | Value  |
+--------------------+-------------------+
| collation_database | latin1_swedish_ci |
+--------------------+-------------------+

设置

CREATE DATABASE 数据库名
[[DEFAULT] CHARACTER SET 字符集名称]
[[DEFAULT] COLLATE 比较规则名称];

ALTER DATABASE 数据库名 
[[DEFAULT] CHARACTER SET 字符集名称] 
[[DEFAULT] COLLATE 比较规则名称];
备注:
character_set_database 和 collation_database 这两个系统变量是只读的,我们不能通过修改这两个变量的值而改变当前数据库的字符集和比较规则。
CREATE DATABASE 数据库名;
如在新建数据库不设置字符集和比较规则的话,将使用服务器级别的字符集和比较规则作为数据库的字符集和比较规则。

表级别

查看

show create table 表名 \G

设置

CREATE TABLE 表名 (列的信息)
[[DEFAULT] CHARACTER SET 字符集名称]
[COLLATE 比较规则名称]]

ALTER TABLE 表名 
[[DEFAULT] CHARACTER SET 字符集名称] 
[COLLATE 比较规则名称]

如在新建数据表不设置字符集和比较规则的话,将使用数据库级别的字符集和比较规则作为数据库的字符集和比较规则。

列级别

查看

show create table 表名 \G

设置

CREATE TABLE 表名(
    列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称],
    其他列...
);

ALTER TABLE 表名 MODIFY 列名 字符串类型 [CHARACTER SET 字符集名称] [COLLATE 比较规则名称];

如在新建数据表列不设置字符集和比较规则的话,将使用数据表级别的字符集和比较规则作为数据库的字符集和比较规则。

备注:

在转换列的字符集时需要注意,如果转换前列中存储的数据不能用转换后的字符集进行表示会发生错误。比方说原先列使用的字符集是utf8,列中存储了一些汉字,现在把列的字符集转换为ascii的话就会出错,因为ascii字符集并不能表示汉字字符。

仅修改字符集或仅修改比较规则

* 只修改字符集,则比较规则将变为修改后的字符集默认的比较规则
* 只修改比较规则,则字符集将变为修改后的比较规则对应的字符集
例如:
mysql> show variables like 'character_set_server';
+----------------------+-------+
| Variable_name | Value |
+----------------------+-------+
| character_set_server | gbk  |
+----------------------+-------+
1 row in set (0.01 sec)
mysql> show variables like 'collation_server';
+------------------+----------------+
| Variable_name | Value |
+------------------+----------------+
| collation_server | gbk_chinese_ci |
+------------------+----------------+
1 row in set (0.01 sec)
mysql> set character_set_server=utf8;
Query OK, 0 rows affected (0.00 sec)
mysql> show variables like 'character_set_server';
+----------------------+-------+
| Variable_name | Value |
+----------------------+-------+
| character_set_server | utf8 |
+----------------------+-------+
1 row in set (0.01 sec)
mysql> show variables like 'collation_server';
+------------------+-----------------+
| Variable_name | Value  |
+------------------+-----------------+
| collation_server | utf8_general_ci |
+------------------+-----------------+
1 row in set (0.01 sec)

客户端和服务器通信中的字符集

查看

SHOW VARIABLES LIKE 'character_set_client';//服务器解码请求时使用的字符集
SHOW VARIABLES LIKE 'character_set_connection';//服务器处理请求时会把请求字符串从character_set_client转为character_set_connection
SHOW VARIABLES LIKE 'character_set_results';//服务器向客户端返回数据时使用的字符集

流程

1、客户端使用操作系统的字符集编码请求字符串,向服务器发送的是经过编码的一个字节串

2、服务器将客户端发送来的字节串采用character_set_client代表的字符集进行解码,将解码后的字符串再按照character_set_connection代表的字符集进行编码

3、如果character_set_connection代表的字符集和具体操作的列使用的字符集一致,则直接进行相应操作,否则的话需要将请求中的字符串从character_set_connection代表的字符集转换为具体操作的列使用的字符集之后再进行操作

4、将从某个列获取到的字节串从该列使用的字符集转换为character_set_results代表的字符集后发送到客户端。

5、客户端使用操作系统的字符集解析收到的结果集字节串。

从根上理解 MySQL 的字符集和比较规则

设置

方法一:(当前会话有效)
SET NAMES 字符集名;

方法二:(当前会话有效)
SET character_set_client = 字符集名; 
SET character_set_connection = 字符集名; 
SET character_set_results = 字符集名;

方法三:配置文件永久生效
[client] default-character-set=utf8

乱码情况

mysql> show variables like 'character_set_client';
+----------------------+-------+
| Variable_name        | Value |
+----------------------+-------+
| character_set_client | gbk   |
+----------------------+-------+

mysql> show variables like 'character_set_connection';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| character_set_connection | utf8 |
+--------------------------+-------+

mysql> show variables like 'character_set_results';
+-----------------------+-------+
| Variable_name  | Value |
+-----------------------+-------+
| character_set_results | utf8 |
+-----------------------+-------+

mysql> show create table student \G
*************************** 1. row ***************************
 Table: student
Create Table: CREATE TABLE `student` (
 `id` int(10) NOT NULL AUTO_INCREMENT,
 `name` varchar(30) DEFAULT NULL,
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8mb4

mysql> insert into student(name) values('张胖');
Query OK, 1 row affected (0.00 sec)
mysql> select * from student where name = '张胖';//显示结果出现乱码
+----+-----------+
| id | name |
+----+-----------+
| 3 | 寮犺儢 |
+----+-----------+
1 row in set (0.00 sec)

出现乱码原因是character_set_client设置的字符集与数据的字符集不一致导致的

解决办法:把character_set_client设置成utf8即可

备注:我们通常都把 character_set_client、character_set_connection、character_set_results 这三个系统变量设置成和客户端使用的字符集一致的情况,这样减少了很多无谓的字符集转换,也可以避免乱码情况的发生。

参考:掘金小册《MySQL 是怎样运行的:从根儿上理解 MySQL》

书籍《MySQL高性能》

相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
7月前
|
存储 人工智能 搜索推荐
详解MySQL字符集和Collation
MySQL支持了很多Charset与Collation,并且允许用户在连接、Server、库、表、列、字面量多个层次上进行精细化配置,这有时会让用户眼花缭乱。本文对相关概念、语法、系统变量、影响范围都进行了详细介绍,并且列举了有可能让字符串发生字符集转换的情况,以及来自不同字符集的字符串进行比较等操作时遵循的规则。对于最常用的基于Unicode的字符集,本文介绍了Unicode标准与MySQL中各个字符集的关系,尤其详细介绍了当前版本(8.0.34)默认字符集utf8mb4。
|
5月前
|
存储 人工智能 关系型数据库
MySQL 8.0 字符集与比较规则介绍
我们都知道 MySQL 8.0 与 MySQL 5.7 的区别之一就是默认字符集从 latin1 改成了 utf8mb4 ,除此之外,MySQL 8.0 下的字符集和比较规则还有没有其他变化呢?本篇文章我们一起来学习下。
333 1
|
6月前
|
存储 自然语言处理 关系型数据库
|
5月前
|
关系型数据库 MySQL 数据库
MySQL设计规约问题之索引的命名规则是什么
MySQL设计规约问题之索引的命名规则是什么
|
6月前
|
SQL 存储 关系型数据库
MySQL数据库进阶第二篇(索引,SQL性能分析,使用规则)
MySQL数据库进阶第二篇(索引,SQL性能分析,使用规则)
|
7月前
|
存储 关系型数据库 MySQL
MySQL各字符集、排序规则的由来、用法,区别和联系
MySQL支持多种字符集和排序规则,这些在数据库设计和数据处理中起着重要作用。下面是它们的由来、用法、区别和联系: 1. **字符集(Character Set)**: - **由来**:字符集定义了数据库中可以存储的字符集合,以及这些字符在数据库中的存储方式。 - **用法**:在创建数据库或表时,可以指定所需的字符集。常见的字符集包括UTF-8、UTF-16、Latin1等。 - **区别和联系**:不同的字符集支持不同的字符范围和存储方式,选择合适的字符集可以确保数据的正确存储和处理。例如,UTF-8支持全球范围内的大多数字符,而Latin1只支持西欧语言字符集。
151 1
|
7月前
|
存储 数据可视化 关系型数据库
Mysql字符集
Mysql字符集
|
7月前
|
存储 SQL 关系型数据库
详解MySQL字符集和Collation
详解MySQL字符集和Collation
679 2
|
7月前
|
弹性计算 安全 关系型数据库
rds安全组规则
云数据库RDS的安全组规则是虚拟防火墙,用于控制网络访问权限,确保数据库安全。配置要点包括:指定RDS实例的安全组,设定入方向规则(如源IP、协议和端口),考虑默认规则的开放程度。根据场景,同组内外的ECS实例需不同配置。管理员应合理规划规则,确保业务需求与安全性平衡,并定期审计更新。
96 3
|
7月前
|
关系型数据库 MySQL Shell
Windows下的mysql字符集格式修改
在Windows上的MySQL 5.7.17,若安装时未设置字符集,可能导致乱码问题。本文提供了解决方案:首先,通过`mysql -uroot -p`登录并使用`show variables like '%char%';`查看当前字符集。然后,有两种修改方法:一是使用Shell命令临时修改9个相关属性为utf8;二是永久修改,在my.ini配置文件中将[mysqld]、[client]、[mysql]下的字符集改为utf8。记得重启MySQL服务以应用更改。此外,还提供了修改数据库和表字符集的SQL命令。

推荐镜像

更多
下一篇
DataWorks