这篇文章详细介绍一下MySQL中的字符集和字符序相关的问题,里里外外地了解一下字符集和字符序的方方面面,同时重点说明一下开发中需要注意的问题。
文章基于MySQL 8.0,也会涉及到5.7版本。主要参考MySQL手册:https://dev.mysql.com/doc/refman/8.0/en/
1. 太长不爱看版
- 字符集(Character Set)是字符的编码规则,字符序(Collation)是字符的排序规则;
- 每一个字符集都包含一定范围的字符;
- 每一个字符集都有一个或多个字符序,其中一个字符序为默认字符序;
- 每一个字符序都有一个相关联的字符集;
- 两个不同的字符集没有相同的字符序;
- 相同数据使用不同的字符序排序结果可能会不同;
- MySQL支持服务(server)、数据库(database)、表(table)、字段(column)以及字符串字面量(string literal)等多个级别的字符集与字符序的设置;
- 库表创建以及程序中尽可能使用
utf8mb4
字符集(可支持emoji); - MySQL中的
utf8
字符集是utf8mb3
字符集的别名,避免使用; - MySQL 5.7的服务默认字符集是
latin1
,而8.0中是utf8mb4
; - 通过
SHOW CHARACTER SET
查看当前服务器所支持的字符集; - 通过
SHOW COLLATION
查看所有的字符序; - MySQL中有多个关于字符集和字符序的系统变量,可以针对全局以及当前session进行设置;
- 通过
SHOW VARIABLES LIKE "character_set%"
查看当前服务以及数据库的字符集设置; - 使用client客户端连接数据库时,如果编码有问题,可以通过
SET NAMES charset_name
来设置和数据库一致的字符集; - 库表内容在不同字符集之前转换可能会发生数据丢失问题。
2. 什么是字符集与字符序
在大多数情况下,我们并不需要了解字符集与字符序,但是在涉及到不同字符集的转换时可能会出现问题,这时了解一下相关的知识还是有帮助的。
我们首先了解一下字符集的原理。
2.1 字符与字符集
字符是我们经常接触到的东西,比如a、中、ß,以及😀等都是字符。
我们知道计算机是通过bit来存储数据的,将人类可识别的字符转换成计算机可存储的形式,这个过程就是编码;字符编码的结果,就是内存编码。
一个字符需要用多少个bit来存储,那就需要知道一共有多少个字符。
所有的字符放在一起就是字符集。
显然,由于使用范围不同,就出现了不同的字符集。比如:
- 汉语中的所有字符构成一个字符集(也包括不是汉字的字符,比如标点符号等);
- 英语中的所有字符构成一个字符集;
- 等等
对于字符集中的每个字符来说,都有两个属性:
- 一个是这个字符在所属字符集中的位置,可以叫做字符序号,或码点(code point);
- 第二个就是这个字符在计算机中的数据表示,即内存编码。
比如ASCII码,只需要8个bit就可以存储所有需要使用的字符了。
但对于汉语来说显然是不够的,因此汉语字符需要更多的bit,来将每个字符进行编码。
这样对于每个国家来说,都可能需要一个将自己使用的字符集编码成计算机内存编码的规则。
那么同一个内存编码,对于不同的字符集来说就可能代表不同的字符:

比如GB18030字符集中的“地球”两个字符的内存编码分别是0xB5D8和0xC7F2,但这两个内存编码在字符集BIG5中代表的字符却是“華⑩”。
这将对我们的程序有很大的影响。
2.2 Unicode字符集与UTF-8
为了解决不同语言编码之间不兼容的问题,Unicode出现了。
Unicode字符集致力于为全世界每一个语言的每一个字符都有统一且唯一的编码:

那么如何将Unicode中的字符映射到内存编码呢?主要有UTF-8、UTF-16和UTF-32等,其中最常用的就是UTF-8。
UTF-8使用1到4个不等的字节来表示所有的字符,其中前128个字符与ASCII一致。
关于Unicdoe的详细信息,可以参考https://home.unicode.org/
2.3 字符序
一个字符集中有多个字符,那么如何对其中的字符进行排序呢?这就是字符序。
简单来说,字符序就是字符排序的规则集合。比如一个字符集有下面几个字符(以及内存编码):
字符 | 内存编码 |
---|---|
A | 00 |
B | 01 |
a | 10 |
b | 11 |
当然我们可以直接按照A>B>a>b的规则来进行排序,这就是这个简单字符集的一个字符序。
如果想让小写字母放在前面,比如a>b>A>B,这又是一种字符序。
如果还想加上大小写无关或大小写相关,那么排序的规则集就会有相应的编码,这就产生了不同的字符序。
字符序主要对字符的排序有影响。
3. MySQL中的字符集与字符序
了解了字符集和字符序之后,来看看MySQL中的字符集与字符序。
3.1 MySQL中的字符集
通过下面的语句来查看MySQL中支持的字符集:
SHOW CHARACTER SET;
结果:
+----------+---------------------------------+---------------------+--------+
| Charset | Description | Default collation | Maxlen |
+----------+---------------------------------+---------------------+--------+
| armscii8 | ARMSCII-8 Armenian | armscii8_general_ci | 1 |
| ascii | US ASCII | ascii_general_ci | 1 |
| big5 | Big5 Traditional Chinese | big5_chinese_ci | 2 |
| binary | Binary pseudo charset | binary | 1 |
| cp1250 | Windows Central European | cp1250_general_ci | 1 |
| cp1251 | Windows Cyrillic | cp1251_general_ci | 1 |
| cp1256 | Windows Arabic | cp1256_general_ci | 1 |
| cp1257 | Windows Baltic | cp1257_general_ci | 1 |
| cp850 | DOS West European | cp850_general_ci | 1 |
| cp852 | DOS Central European | cp852_general_ci | 1 |
| cp866 | DOS Russian | cp866_general_ci | 1 |
| cp932 | SJIS for Windows Japanese | cp932_japanese_ci | 2 |
| dec8 | DEC West European | dec8_swedish_ci | 1 |
| eucjpms | UJIS for Windows Japanese | eucjpms_japanese_ci | 3 |
| euckr | EUC-KR Korean | euckr_korean_ci | 2 |
| gb18030 | China National Standard GB18030 | gb18030_chinese_ci | 4 |
| gb2312 | GB2312 Simplified Chinese | gb2312_chinese_ci | 2 |
| gbk | GBK Simplified Chinese | gbk_chinese_ci | 2 |
| geostd8 | GEOSTD8 Georgian | geostd8_general_ci | 1 |
| greek | ISO 8859-7 Greek | greek_general_ci | 1 |
| hebrew | ISO 8859-8 Hebrew