举个栗子

好读书,不求甚解

谈谈MySQL中的utf8和utf8mb4

Kevalin's Avatar 2019-12-26

UTF-8使用一至六个字节为每个字符编码(尽管如此,2003年11月UTF-8被RFC 3629重新规范,只能使用原来Unicode定义的区域,U+0000到U+10FFFF,也就是说最多四个字节)。然而在MySQL的utf8编码的每个符号最多三个字节,所以它的别名也叫utf8mb3,它支持的范围只有U+000000到U+00FFFF,当我们存入一个正常UTF-8编码的字符但有超过MySQL的utf8字符编码范围的内容时就会有问题了,例如Emoji表情。

我们要清楚的知道,MySQL的utf8是不能等同于我们一般认为的UTF-8的,它不能提供完整的Unicode支持,所以是有可能导致数据丢失或安全性问题。

MySQL在5.5.3之后提供了一个新的编码方式──utf8mb4,它支持正常的UTF-8和完整的Unicode,甚至是星座符号,例如♈,哈哈,是不是强大了不少。因此,我们在使用MySQL时,最好使用utf8mb4这个编码方式。

查看当前MySQL字符集

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
mysql> SHOW VARIABLES WHERE Variable_name LIKE 'character\_set\_%' OR Variable_name LIKE 'collation%';
+--------------------------+--------------------+
| Variable_name | Value |
+--------------------------+--------------------+
| character_set_client | utf8mb4 |
| character_set_connection | utf8mb4 |
| character_set_database | utf8mb4 |
| character_set_filesystem | binary |
| character_set_results | utf8mb4 |
| character_set_server | utf8mb4 |
| character_set_system | utf8 |
| collation_connection | utf8mb4_unicode_ci |
| collation_database | utf8mb4_unicode_ci |
| collation_server | utf8mb4_unicode_ci |
+--------------------------+--------------------+
10 rows in set (0.00 sec)

上面展示的参数还是很多的,它们是什么意思,相互之间又有什么关系呢?

MySQL有两个字符集概念:一个就是字符集本身(character开头的),一个是字符集校验规则(collation开头的)。字符集影响数据在传输和存储过程中的处理方式,而字符集校验则影响ORDER BY和GROUP BY这些排序方式。

  • character_set_client客户端使用的字符集,相当于网页中的字符集设置
  • character_set_connection 连接数据库的字符集设置类型,如果代码中没有指明连接数据库使用的字符集类型就按照服务器端默认的字符设置
  • character_set_database数据库服务器中某个库使用的字符集设定,如果建库时没有指明,将使用服务器安装时指定的字符集设置
  • character_set_filesystem文件系统格式
  • character_set_results数据库给客户端返回时使用的字符集设定,如果没有指明,使用服务器默认的字符集
  • character_set_server服务器安装时指定的默认字符集设定
  • character_set_system数据库系统使用的字符集设定
  • collation_connection连接字符集的校对规则
  • collation_database 默认数据库使用的校对规则。当默认数据库改变时服务器则设置该变量。如果没有默认数据库,变量的值同collation_server
  • collation_server服务器的默认校对规则

如果你的数据库还不是5.5.3+版本,请先升级你的MySQL。当然升级前备份一下你的数据库啦,以防万一。

修改databases,tables和columns字符集的方法

1
2
3
4
5
6
7
# For each database:
ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;
# For each table:
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
# For each column:
ALTER TABLE table_name CHANGE column_name column_name VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
# (Don’t blindly copy-paste this! The exact statement depends on the column type, maximum length, and other properties. The above line is just an example for a `VARCHAR` column.)

还有一点要注意的是utf8mb4是向下兼容utf8的,所以也不用担心改变字符集导致数据丢失的问题。

修改连接,客户端和服务器字符集

在代码中可以通过简单的SET NAMES utf8mb4来完成更换。当使用SET NAMES utf8mb4时,其实就是执行了下面三句:

1
2
3
SET character_set_client = utf8mb4;
SET character_set_results = utf8mb4;
SET character_set_connection = utf8mb4;

而服务器的字符集一般是在启动配置/etc/my.cnf中配置的,例如:

1
2
3
4
5
6
7
8
9
10
[client]
default-character-set = utf8mb4

[mysql]
default-character-set = utf8mb4

[mysqld]
character-set-client-handshake = FALSE
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci

总而言之,从现在开始,我们 尽量在MySQL中使用utf8mb4而不要再使用utf8啦!!!

参考

本文作者 : Kevalin
本文使用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议
本文链接 : https://kevalin.github.io/2019/12/26/%E8%B0%88%E8%B0%88MySQL%E4%B8%AD%E7%9A%84utf8%E5%92%8Cutf8mb4/