MySQL中没法存储Emoji字符,源自于MySQL 5.5以前utf8编码只支持最大3个字节,而Emoji须要4个字节。从MySQL 5.5开始,其utf8编码开始有了支持4个字节的utf8类型:utf8mb4 . java
一般,若是你的MySQL版本是5.5+但又没法在某个具体的列存储Emoji字符,就是源自于这个列的类型还停留于过去的utf8类型,没有升级到最新的支持4字节的utf8mb4. mysql
解决方案的思路也很简单,就是在确保你的MySQL是5.5+的前提下,将须要存储Emoji字符的列的编码改成utf8mb4. sql
网上的大部分资料采用了更改 "列、表、库" 的编码类型,再配上修改MySQL配置文件,并重启MySQL的方式来解决问题:ui
-- 修改一列: 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字符的存储问题,那就只须要修改这个列的编码类型便可。若是确实须要修改到"表、库"这个级别,那再作修改不迟。url
作完这一步后,应该能够在db客户端直接存储Emoji字符了。可是,对于须要链接到MySQL的应用来说,仅仅上述步骤的修改还不够,还没法使应用将Emoji字符成功地存储MySQL。这涉及到应用与MySQL创建链接的问题。code
因为咱们想要不重启MySQL,那么MySQL当中默认给出的 "创建新链接" (set connection) 所支持的字符编码依旧是utf8。虽然db里面的某个特定的列已经支持了utf8mb4,但"链接"不支持对utf8mb4字符的传输,Emoji字符也就没法顺利运输到db中。server
因此问题就变成了,如何在不重启MySQL的前提下,从新设置connection的字符编码。xml
有一条MySQL命令是 set names 'xxx'
,会将character_set_client、character_set_connection、character_set_results的编码统一设置。使用这条命令 set names utf8mb4;
即可以达到咱们的目的。ci
但问题是,应该在哪里设置这条命令呢?不少人会直接在本身的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中去。