备注:本文修订于2020年7月1日
1、字符编码utf8和utf8mb4的历史渊源
UTF-8 编码是一种变长的编码机制,可以用 1 ~ 4 个字节存储字符。但是,因为历史遗留问题,MySQL 中的 utf8 编码并不是真正的 UTF-8,而是阉割版的,最长只有3个字节。当遇到占4个字节的 UTF-8 编码,例如 emoji 字符或者复杂的汉字,会导致存储异常。
MySQL 在 5.5.3 之后增加了 utf8mb4 编码,mb4 就是 most bytes 4 的意思,专门用来兼容四字节的 unicode。好在 utf8mb4 是 utf8 的超集,除了将编码改为 utf8mb4 外,不需要做其他转换。当然,为了节省空间,一般情况下使用 utf8 也就够了。
既然 utf8 能够存下大部分中文汉字,那为什么还要使用 utf8mb4 呢?原来 MySQL 支持的 utf8 编码最大字符长度为 3 字节,如果遇到 4 字节的宽字符就会插入异常了。
三个字节的 UTF-8 最大能编码的 Unicode 字符是 0xffff,也就是 Unicode 中的基本多文种平面(BMP)。也就是说,任何不在基本多文本平面的 Unicode 字符,都无法使用 MySQL 的 utf8 字符集存储。包括 Emoji 表情(Emoji 是一种特殊的 Unicode 编码,常见于 ios 和 android 手机上)和很多不常用的汉字,以及任何新增的 Unicode 字符等等。
2、字符编码utf8和utf8mb4的特点
utf8 编码特点:
(1)最大字符长度为 3 字节,如果遇到 4 字节的字符就会出现错误了。
(2)无法存贮表情和不常用汉字
(3)消耗空间比 utf8mb4 少
utf8mb4 编码特点:
(1)最大字符长度为4字节
(2)对于 CHAR 类型数据,存储会多消耗一些空间。
(3)多了表情的支持
3、字符排序
字符除了需要存储,还需要排序或比较大小。推荐用 utf8mb4_unicode_ci,但是用 utf8mb4_general_ci 也没啥问题。
其实,utf8mb4_unicode_ci 和 utf8mb4_general_ci 对于中文和英文来说,其实是没有任何区别的。对于我们开发的国内使用的系统来说,随便选哪个都行。只是对于某些西方国家的字母来说,utf8mb4_unicode_ci 会比 utf8mb4_general_ci 更符合他们的语言习惯一些,general 是 MySQL 一个比较老的标准了。
MySQL 8.0 默认的是 utf8mb4_0900_ai_ci,属于 utf8mb4_unicode_ci 中的一种,具体含义如下:
(1)uft8mb4 表示用 utf8mb4 编码方案,每个字符最多占4个字节。
(2)0900 指的是 Unicode 校对算法版本。(Unicode归类算法是用于比较符合Unicode标准要求的两个Unicode字符串的方法)。
(3)ai 指的是口音不敏感。也就是说,排序时e,è,é,ê和ë之间没有区别。ci 表示不区分大小写。也就是说,排序时p和P之间没有区别。备注:
如果需要重音灵敏度和区分大小写,则可以使用 utf8mb4_0900_as_cs 代替。
扩展阅读