Application无法传递Emoji字符到MySQL的问题

3次阅读

共计 2411 个字符,预计需要花费 7 分钟才能阅读完成。

MySQL 中无法存储 Emoji 字符,源自于 MySQL 5.5 之前 utf8 编码只支持最大 3 个字节,而 Emoji 需要 4 个字节。从 MySQL 5.5 开始,其 utf8 编码开始有了支持 4 个字节的 utf8 类型:utf8mb4 .
通常,如果你的 MySQL 版本是 5.5+ 但又无法在某个具体的列存储 Emoji 字符,就是源自于这个列的类型还停留于过去的 utf8 类型,没有升级到最新的支持 4 字节的 utf8mb4.
解决方案的思路也很简单,就是在确保你的 MySQL 是 5.5+ 的前提下,将需要存储 Emoji 字符的列的编码改为 utf8mb4.
网上的大部分资料采用了更改 “ 列、表、库 ” 的编码类型,再配上修改 MySQL 配置文件,并重启 MySQL 的方式来解决问题:
— 修改一列:
ALTER TABLE table_name CHANGE column_name column_name VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

— 修改表:
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;

— 修改库:
ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci;

— ==============================

— 修改配置文件 /etc/my.cnf
[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 的重启,对生产环境来讲,重启 db 是一件代价极其高昂的事情。
事实上,如果只是某个列存在 Emoji 字符的存储问题,那就只需要修改这个列的编码类型即可。如果确实需要修改到 ” 表、库 ” 这个级别,那再做修改不迟。
做完这一步后,应该可以在 db 客户端直接存储 Emoji 字符了。但是,对于需要连接到 MySQL 的应用来讲,仅仅上述步骤的修改还不够,还无法使应用将 Emoji 字符成功地存储 MySQL。这涉及到应用与 MySQL 建立连接的问题。
由于我们想要不重启 MySQL,那么 MySQL 当中默认给出的 “ 建立新连接 ” (set connection) 所支持的字符编码依旧是 utf8。虽然 db 里面的某个特定的列已经支持了 utf8mb4,但 ” 连接 ” 不支持对 utf8mb4 字符的传输,Emoji 字符也就无法顺利运输到 db 中。
所以问题就变成了,如何在不重启 MySQL 的前提下,重新设置 connection 的字符编码。
有一条 MySQL 命令是 set names ‘xxx’,会将 character_set_client、character_set_connection、character_set_results 的编码统一设置。使用这条命令 set names utf8mb4; 便可以达到我们的目的。
但问题是,应该在哪里设置这条命令呢?很多人会直接在自己的 MySQL 客户端运行这条命令,但发现自己的应用依旧无法正确传递 Emoji 字符。这是因为,当你在 MySQL 客户端运行这条命令时,只是设置了你的客户端同 MySQL 的 connection 字符编码,但你的应用却使用了自己的 connection,当然无法达到目的。
所以正确的做法是,你需要在自己应用建立 connection 后,在代码中运行这条命令。
而如果你使用的是 Druid DataSource(如果你使用的是 Tomcat DataSource,那么你可以大胆切换到 Druid DataSource),那么这件事情就更容易了,只需要在配置文件的 connectionInitSqls 中完成这件事。以 Java 为例,你只需要:
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(“com.mysql.jdbc.Driver”);
dataSource.setUrl(url);
dataSource.setUsername(userName);
dataSource.setPassword(password);

// set ‘utf8mb4’ to support emoji character
dataSource.setConnectionInitSqls(Arrays.asList(“set names utf8mb4;”));
如果你使用的是 xml 来配置 bean,则只需要:
<bean id=”dataSource” class=”com.alibaba.druid.pool.DruidDataSource” init-method=”init” destroy-method=”close”>
<property name=”driverClassName” value=”${jdbc-driver}”/>
<property name=”url” value=”${jdbc-url}”/>
<property name=”username” value=”${jdbc-user}”/>
<property name=”password” value=”${jdbc-password}”/>

<property name=”connectionInitSqls” value=”set names utf8mb4;”/>

</bean>
如此,便能在不重启 MySQL 的情况下让你应用将 Emoji 字符传递到 db 中去。

正文完
 0