MySQL中的utf8mb4和utf8字符集有什么区别?

我已经知道ASCII, UTF-8, UTF-16和UTF-32编码; 但是我很好奇utf8mb4编码组与MySQL服务器中定义的其他编码类型有什么不同。

使用utf8mb4而不是utf8有什么特别的好处/建议吗?


UTF-8是一种变长编码。对于UTF-8,这意味着存储一个代码点需要1到4个字节。然而,MySQL的编码名为“utf8”(“utf8mb3”的别名),每个代码点最多只能存储3个字节。

因此字符集“utf8”/“utf8mb3”不能存储所有的Unicode码位:它只支持0x000到0xFFFF的范围,即所谓的“基本多语言平面”。 请参见Unicode编码的比较。

这是(同一页面的前一个版本)MySQL文档说的:

The character set named utf8[/utf8mb3] uses a maximum of three bytes per character and contains only BMP characters. As of MySQL 5.5.3, the utf8mb4 character set uses a maximum of four bytes per character supports supplemental characters: For a BMP character, utf8[/utf8mb3] and utf8mb4 have identical storage characteristics: same code values, same encoding, same length. For a supplementary character, utf8[/utf8mb3] cannot store the character at all, while utf8mb4 requires four bytes to store it. Since utf8[/utf8mb3] cannot store the character at all, you do not have any supplementary characters in utf8[/utf8mb3] columns and you need not worry about converting characters or losing data when upgrading utf8[/utf8mb3] data from older versions of MySQL.

所以如果你想让你的列支持存储位于BMP之外的字符(你通常想要),比如emoji,使用"utf8mb4"。请参见实际使用中最常见的非bmp Unicode字符是什么?


utf8mb4字符集很有用,因为现在我们不仅需要支持存储语言字符,还需要支持存储符号、新引入的表情符号等等。

Mathias Bynens写了一篇关于如何在MySQL数据库中支持完整的Unicode的文章,这篇文章也可以解释这个问题。


摘自MySQL 8.0参考手册:

utf8mb4:使用one to的Unicode字符集的UTF-8编码 每个字符四个字节。 utf8mb3:使用one to的Unicode字符集的UTF-8编码 每个字符三个字节。

在MySQL中,utf8目前是utf8mb3的别名,已弃用,并将在未来的MySQL版本中删除。此时,utf8将成为utf8mb4的引用。

因此,不管这个别名如何,您都可以有意识地为自己设置一个utf8mb4编码。

为了完成答案,我想在下面添加@ williamamentriken的评论(也摘自手册):

为了避免utf8含义的歧义,可以考虑为字符集引用显式指定utf8mb4,而不是utf8。


MySQL在5.5.3之后添加了这个utf8mb4代码,Mb4是最多字节4的意思,专门设计为兼容4字节的Unicode。幸运的是,UTF8MB4是UTF8的超集,只是不需要将编码转换为UTF8MB4。当然,为了节省空间,一般使用UTF8就足够了。

最初的UTF-8格式使用1到6个字节,最多可以编码31个字符。最新的UTF-8规范只使用一到四个字节,最多可以编码21位,仅代表所有17个Unicode平面。UTF8是Mysql中的字符集,最多只支持三个字节的UTF-8字符,这是Unicode中的基本多文本平面。

要在Mysql中保存4字节长的UTF-8字符,您需要使用UTF8MB4字符集,但只需5.5。支持3个版本后(查看版本:选择版本();)。我认为为了获得更好的兼容性,你应该总是使用UTF8MB4而不是UTF8。对于char类型的数据,UTF8MB4占用更多的空间,并且根据Mysql的官方建议,使用VARCHAR而不是char。

在MariaDB中,utf8mb4在服务器配置中没有显式设置时作为默认的CHARSET,因此使用COLLATE utf8mb4_unicode_ci。

参考MariaDB CHARSET & COLLATE单击

CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

utf8是MySQL较老的、有缺陷的UTF-8实现,它正在被弃用。 utf8mb4是他们为其固定的UTF-8实现命名的,也是您现在应该使用的。

In their flawed version, only characters in the first 64k character plane - the basic multilingual plane - work, with other characters considered invalid. The code point values within that plane - 0 to 65535 (some of which are reserved for special reasons) can be represented by multi-byte encodings in UTF-8 of up to 3 bytes, and MySQL's early version of UTF-8 arbitrarily decided to set that as a limit. At no point was this limitation a correct interpretation of the UTF-8 rules, because at no point was UTF-8 defined as only allowing up to 3 bytes per character. In fact, the earliest definitions of UTF-8 defined it as having up to 6 bytes (since revised to 4). MySQL's original version was always arbitrarily crippled.

回到MySQL发布这个功能的时候,这个限制的结果还不是很糟糕,因为大多数Unicode字符都在第一个平面中。从那时起,越来越多新定义的字符范围被添加到Unicode中,其值在第一个平面之外。Unicode本身定义了17个平面,但到目前为止只使用了其中的7个。

为了不破坏旧代码,MySQL保留了损坏的实现,并将更新的、固定的版本称为utf8mb4。这导致了一些混淆,它的名字被误解为好像它是某种UTF-8的扩展或UTF-8的替代形式,而不是MySQL对真正的UTF-8的实现。

MySQL的未来版本将最终淘汰旧版本,现在可以认为它已弃用。在可预见的将来,您需要使用utf8mb4来确保正确的UTF-8编码。经过足够的时间后,当前的utf8将被删除,在未来的某个日期,utf8将再次上升,这次指的是固定版本,尽管utf8mb4将继续明确地指固定版本。