Mysql 中的 utf-8
mysql 中的 utf-8
导读
问题:在用户评论中带有 emoji表情时,utf-8编码的数据库抛出异常
`Incorrect string value: ‘\xF0\x9F\x98\x83 <…’ for column ‘comment’ at row 1`
在网上找解决方案:将相关字段字符集设置为 utf-8mb4
,然后问题解决。
疑问:在我的理解中, utf-8
是用来存储各国语言字符的,utf-8mb4
是难道是专门用来存储 emoji的?
字符集及编码简介
要明白这个问题,首先需要先了解什么是字符集及编码方式。
字符集(Character set)是多个字符的集合,字符编码是在字符集内用于比较字符的一套规则,即字符集的排序规则。
首先我们知道,计算机使用 0
和 1
存储信息。最早的计算机在设计时采用 8个比特(bit)作为一个字节(byte)。所以,一个字节能表示的最大的整数就是 255
(二进制 11111111
,十进制 255
),0
-255
被用来表示大小写英文字母、数字和一些符号,
这个编码表被称为 ASCII编码,比如大写字母 A
的编码是 65
,小写字母 z
的编码是 122
小技巧:键盘按住
alt
+ 对应 ASCII 码,输入相应字符
时代在进步,计算机的普及和发展导致新的问题出现,对于中文、日文等文字符号,ASCII字符集并不能满足,于是出现了 UNICODE字符集,
通过扩充比特位的方式,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。将字符转为二进制编码的规则就被称为编码方式。
UNICODE通常用两个字节表示一个字符。为什么是 2字节呢?可能是因为在 UNICODE早期,设计 Unicode的团队考查了世界上主要的文字之后,感觉用 2个字节也就是最多 65536个字符应该够用了,设定编码方式为 UCS2。但是后面出现了更多的字符(现在 Unicode包含了 12万 8千个字符),于是只能再使用 UCS4或 UTF-32将字符以 4字节保存。
问题看起来解决了,但是却有个问题:很多字符使用这种编码并不高效,如用 ASCII表示的 00000001用 UTF-32就会存储很多无必要的高比特位。为了解决这个问题,就出现了其他的非固定长度编码方式,也就是本文的主角 ———— UTF-8,最短的 UTF-8字符只需要使用 1个字节(同 ASCII),最长是 4个字节。UTF-8相比 UTF-32更加节约空间。在 UTF-8中,像“1”这样的字符占用 1字节,“💩”这样的 emoji占用 4字节。其他字符占用 2或者 3字节。更小的空间占用也意味着加载与传输速度会快更多。
MYSQL 中的“utf-8”
可以注意到,上文我提到一个例子:UTF-8中 “💩”占用 4字节。这就回到了本文一开始的问题:utf-8编码的数据库在存储 emoji表情时出错。
按照上述的介绍,应该是可以存进去的?但是我们看下 MYSQL文档上对其 utf-8字符编码的解释:
utf8是 utf8mb3 字符集的别名
该 utf8mb3 字符集有以下特点:
* 仅支持BMP字符(不支持增补字符)
* 每个多字节字符最多需要三个字节
划重点:每个多字节字符最多需要三个字节,这就表明了 MYSQL中 utf-8并不是传统意义上的 utf-8。
我们再看下 utf-8mb4
该utfmb4字符集有以下特点:
* 支持BMP和补充字符。
* 每个多字节字符最多需要四个字节。
也就是说,对于 MYSQL来说,utf-8mb4(mb4即 most byte 4)才是真正意义上的 utf-8。当我们 MYSQL数据库的字符集编码为 utf-8
,
存储需要 4字节表示的 emoji表情时,自然会出错了。
后话
MYSQL为什么会用这种奇怪的方式来定义字符集编码,在网上找了许久的答案没有准确的说法,更多的是把它看作 MYSQL开发过程中的一个失误。
如果大家后续清楚了原因,也可以说出来一起交流下。
另外在寻找问题的过程中也了解到其他一些知识点,跟大家简单分享下:
MySQL可以使用对种字符集和检验规则来组织字符。MySQL服务器可以支持多种字符集,在同一台服务器,同一个数据库,甚至同一个表的不同字段都可以指定使用不同的字符集。相比 oracle等其他数据库管理系统,在同一个数据库只能使用相同的字符集,MySQL明显存在更大的灵活性。
数据库设置字符集的排序规则,如
utf8_general_ci
与utf8_unicode_ci
,general
与unicode
代表的是排序规则,使用general
更快速,使用unicode
更精确(德语等比较特殊的语种使用),ci
即 case insensitive, 即“大小写不敏感”。
原文地址:https://www.jianshu.com/p/46bf6d3203c6