文章目录
  1. 1. 1. 背景知识
  2. 2. 2. 改造步骤
    1. 2.1. 2.1 MySQL服务端
      1. 2.1.1. 2.1.1 修改/etc/my.cnf并重启MySQL服务器
    2. 2.2. 2.2 MySQL数据库
      1. 2.2.1. 2.2.1 修改数据库编码为utf8mb4
      2. 2.2.2. 2.2.2 修改数据表编码为utf8mb4
      3. 2.2.3. 2.2.3 修改表字段编码为utf8mb4
    3. 2.3. 2.3 Java客户端
      1. 2.3.1. 2.3.1 升级JDBC驱动
      2. 2.3.2. 2.3.2 JDBC数据库连接串
      3. 2.3.3. 2.3.3 数据库连接配置
  3. 3. 3. 使用utf8mb4后需要注意的地方
    1. 3.1. 3.1 字段长度限制
    2. 3.2. 3.2 索引长度限制
    3. 3.3. 3.3 行长度限制
  4. 4. 4. 总结

最近在项目中需要支持用户输入emoji字符(如🚀),由于数据库的编码用的是utf8,所以需要做一些改造来予以支持。

1. 背景知识

  • UTF8
    • 在MySQL中utf8编码的字符会占用1-3个字节来存储数据
    • 只支持BMP#Basic_Multilingual_Plane)字符
  • UTF8MB4
    • 在MySQL中utf8mb4编码的字符会占用1-4个字节来存储数据
    • 支持BMP#Basic_Multilingual_Plane)字符
    • 还支持Supplementary#Supplementary_Multilingual_Plane)字符,比如emoji符号
    • MySQL 5.5以上才有utf8mb4编码

所以,从上面可以看出,utf8mb4是utf8的超集,所以从utf8升级到utf8mb4,理论上是没有任何问题的,不过对数据库版本有要求(5.5以上)。

2. 改造步骤

2.1 MySQL服务端

2.1.1 修改/etc/my.cnf并重启MySQL服务器

这一步非必须,如果实在由于某些原因无法修改数据库配置,可以通过后面2.3.3部分的客户端手动配置来解决。

[mysqld]
character-set-server=utf8mb4
collation-server=utf8mb4_general_ci

2.2 MySQL数据库

2.2.1 修改数据库编码为utf8mb4

ALTER DATABASE `DBName` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci;

可以通过以下SQL来生成alter语句:

use information_schema;
SELECT concat("ALTER DATABASE `",table_schema,"` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci;") as _sql
FROM `TABLES` where table_schema like "yourDbName" group by table_schema;

2.2.2 修改数据表编码为utf8mb4

ALTER TABLE `TableName` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;

可以通过以下SQL来生成所有表的alter语句:

use information_schema;
SELECT concat("ALTER TABLE `",table_schema,"`.`",table_name,"` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci;") as _sql
FROM `TABLES` where table_schema like "yourDbName" group by table_schema, table_name;

2.2.3 修改表字段编码为utf8mb4

如果表字段没有特别指定编码的,就会默认使用表的编码,所以这步一般都可以省略。不过如果有不一样的话,可以通过下面SQL来修改。

ALTER TABLE `TableName ` CHANGE `ColumnName ` `ColumnName` `DataType(Length)` CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci DEFAULT `xx` Comment `xx`;

2.3 Java客户端

2.3.1 升级JDBC驱动

确保mysql connector版本高于5.1.13,参见release note

2.3.2 JDBC数据库连接串

由于目前的java mysql connector还不支持utf8mb4,所以在jdbc的数据库连接串还只能使用utf8

jdbc:mysql://database_ip:3306/database_name?characterEncoding=utf8

2.3.3 数据库连接配置

如果在2.1部分,已经修改了数据库的配置并重启,那么这一步可以省略,因为mysql connector会自动继承服务器的设置。

如果2.1部分由于各种原因没有修改的话,那么就需要在客户端这里做设置了。

具体来说,就是在每个数据库连接建立的时候,通过运行set names utf8mb4来显式设置客户端连接的encoding为utf8mb4

如果客户端用的是tomcat-jdbc的话,可以通过initSQL属性来做设置。

initSQL - the ability to run a SQL statement exactly once, when the connection is created

对spring-boot应用而言,就是设置spring.datasource.initSQL属性:

spring.datasource.initSQL=set names utf8mb4

3. 使用utf8mb4后需要注意的地方

由于utf8mb4的字节长度是1-4个字节,而utf8的字节长度是1-3个字节,所以会有一些限制的变化。

3.1 字段长度限制

MySQL中的字段类型都有长度限制,比如varchar的最长字节长度是65535,所以使用utf8编码的时候,可以指定字段最长为65535/3=21845。如果使用utf8mb4编码的话,由于字符最长会占用4个字节,所以字段最长只能为65535/4=16383。

3.2 索引长度限制

MySQL中的索引也有长度限制: 767字节,所以使用utf8编码的的时候,可以指定索引字段最长为255字节,但是指定utf8mb4的话,只能索引191字节。

KEY XX_Index (XX(191))

3.3 行长度限制

MySQL中的行也有长度限制: 65535字节,所以当字段编码从utf8变为utf8mb4的时候,可能也会需要缩短部分字段的长度来满足行的长度限制。

4. 总结

从上面的改造步骤来看,从utf8到utf8mb4还是比较容易的,而且理论上来说是没有风险的,所以推荐大家尽快采用utf8mb4。另外,对于新的应用可以一上来就使用utf8mb4编码,以免真的碰到问题了再来改造过于被动。

原文地址:MySQL支持emoji字符

文章目录
  1. 1. 1. 背景知识
  2. 2. 2. 改造步骤
    1. 2.1. 2.1 MySQL服务端
      1. 2.1.1. 2.1.1 修改/etc/my.cnf并重启MySQL服务器
    2. 2.2. 2.2 MySQL数据库
      1. 2.2.1. 2.2.1 修改数据库编码为utf8mb4
      2. 2.2.2. 2.2.2 修改数据表编码为utf8mb4
      3. 2.2.3. 2.2.3 修改表字段编码为utf8mb4
    3. 2.3. 2.3 Java客户端
      1. 2.3.1. 2.3.1 升级JDBC驱动
      2. 2.3.2. 2.3.2 JDBC数据库连接串
      3. 2.3.3. 2.3.3 数据库连接配置
  3. 3. 3. 使用utf8mb4后需要注意的地方
    1. 3.1. 3.1 字段长度限制
    2. 3.2. 3.2 索引长度限制
    3. 3.3. 3.3 行长度限制
  4. 4. 4. 总结