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中去。