mysql中的utf8字符集与标准UTF-8的区别

时间:2022-10-21 15:42:32
尽管字面上非常相似,但mysql的utf-8的覆盖范围仅仅是所有UTF-8字符集的一部分。这非常容易误导初学者。

UTF-8是UCS字符集的一种编码方式,可能将一个字符编码为1个字节,2个字节,3个字节,或者4个字节。
编码为1个字节的字符就是ASCII码(有时称为latin文字符号),包含了拉丁语言中使用的符号,如拉丁字母、数字、标点等。 编码为2个字节的字符包括了欧洲和中东地区语言(如希腊语、希伯来语、亚美尼亚语、阿拉伯语、叙利亚语等)中使用的符号。 编码为3个字节的字符包括了中文日文韩文等亚洲语言使用的符号。 编码为4个字节的字符包括了一些特殊的符号,比如一些表情符号。
日常使用的绝大多数符号,都包括在前三种里。这三种合起来占据了unicode编码空间的第一个平面。unicode一共有17个平面。第一个平面称为Basic Multilingual Plane,简称为BMP,一共包含了2^16=65536个编码。这些编码里包括了日常使用的各种可见符号、可见和不可见控制符号、用于UTF-16编码扩展的特殊符号、一些私有用途符号,以及少数未分配符号。
mysql的utf8字符集就是对应于unicode的BMP平面。它可以用来存储所有BMP字符。因为BMP字符在使用UTF-8编码时最多占据3个字节,所以mysql在为char(n)数据类型分配存储空间时是预留了3*n个字节的空间。
如果应用从不使用UTF-8编码为四个字节的字符,一切都没有问题。但如果使用了,那么就必须使用mysql从5.5版本开始提供的另一种字符集:utf8mb4(字面理解应该是multi-byte-4的意思吧?)。这个字符集解决了utf8中三个字节的限制问题,可以存储占用4个字节的unicode字符,也就是现在可以存储全部的unicode字符了。同时,原有的utf8现在有了一个新名字:uft8mb3(仍然可以使用原来的utf8)。
一个4个字节UTF-8字符的例子,是在mac或者iOS设备上输入文字时的特殊字符,如使用拼音输入kong,备选中会有一个非汉字的图形字符mysql中的utf8字符集与标准UTF-8的区别,它的unicode编号是1F233,UTF-8编码是F0 9F 88 B3(4个字节),UTF-16编码是D83C DE33(占用两个16位单元,也是4个字节)。这个字符就无法存储进mysql的utf8字符集中,必须使用utf8mb4才行。
参考文章:https://mathiasbynens.be/notes/mysql-utf8mb4
注: 如果要把一个已有的表的字符集从utf8改为utf8mb4以支持BMP范围以外的unicode字符,需要执行以下操作: 1)修改表的默认字符集设置:

alter table xxx set default character set = utf8mb4;alter table xxx convert to character set utf8mb4;

2)如果想把全库的默认字符集也改了,可以:

alter database xxx set default character set = utf8mb4;

3)修改my.cnf中的服务器默认字符集设置

server_character_set = utf8mb4

mysql文档中说该设置仅仅影响新建数据库时为新数据库选择何种默认字符集,所以我理解更改一个已有数据库不需要修改它的值(试想我在该mysql服务器上有好多数据库,但只想对其中一个启用utf8mb4)。但从实际使用来看,必须把这个配置设为utf8mb4。具体原因我还没搞明白。可能这个变量还用作在应用建立数据库连接时的缺省字符集? 4)重新启动mysql服务。需要这一步是因为我们改动了my.cnf中的配置