Mysql存儲微信Emoji表情問題

問題

Tomcat 中報 Java 以下錯誤:java

java.sql.SQLException: Incorrect string value: '\xF0\x9F\x8D\x87 \xE7...' for column 'name' at row 1
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1078)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4187)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4119)
        at com.mysql.jdbc.MysqlIO.sendCommand(MysqlIO.java:2570)
        at com.mysql.jdbc.MysqlIO.sqlQueryDirect(MysqlIO.java:2731)
        at com.mysql.jdbc.ConnectionImpl.execSQL(ConnectionImpl.java:2815)
        at com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:2155)
        at com.mysql.jdbc.PreparedStatement.execute(PreparedStatement.java:1379)
        at com.alibaba.druid.filter.FilterChainImpl.preparedStatement_execute

上面錯誤意思是 mysql 數據庫中 name 字段插入不正確的字符串值name 字段是記錄微信呢稱,設計之出沒有考慮到微信呢稱中使用 Emoji 表情,致使寫入數據失敗。mysql

問題根本緣由

Mysql 版本是 5.7.22,當時使用下面命令建立數據庫,使用 utf8 編碼。但 utf8 不支持 Emoji 表情。sql

create database if not exists my_db default charset utf8 collate utf8_general_ci;

utf8 爲何不支持 Emoji

utf8不支持emoji,是由於emoji是用4個字節存儲的字符,而mysql的utf8只能存儲1-3個字節的字符。數據庫

解決思路

  • (1)Mysql 服務器 client、mysql、mysqld 中須要顯式指定字符集爲 utf8mb4
  • (2)在(1)的服務器上建立的db,須要爲 utf8mb4 字符集,COLLATEutf8mb4_unicode_ciutf8mb4_general_ci
  • (3)在(2)的db中建立 table 和存放emoji字段的字符集爲 utf8mb4collateutf8mb4_unicode_ciutf8mb4_general_ci
  • (4)MySQL驅動最低不能低於 5.1.13,5.1.34 可用。

utf8_unicode_ciutf8_general_ci 比較:服務器

  • utf8_unicode_ci 和 utf8_general_ci 對中、英文來講沒有實質的差異。
  • utf8_general_ci 校對速度快,但準確度稍差。
  • utf8_unicode_ci 準確度高,但校對速度稍慢。

小結:若是你的應用有德語、法語或者俄語,請必定使用 utf8_unicode_ci。通常用 utf8_general_ci 就足夠。微信

utf8mb4 mysql最低版本支持

注意utf8mb4 最低 mysql 版本支持爲 5.5.3+,若不是,請升級到較新版本。ui

MySQL 在 5.5.3 以後增長了 utf8mb4 字符編碼,mb4即 most bytes 4。簡單說 utf8mb4 是 utf8 的超集並徹底兼容utf8,可以用四個字節存儲更多的字符。編碼

但拋開數據庫,標準的 UTF-8 字符集編碼是能夠用 1~4 個字節去編碼21位字符,這幾乎包含了是世界上全部能看見的語言了。
然而在MySQL裏實現的utf8最長使用3個字節,也就是隻支持到了 Unicode 中的 基本多文本平面 (U+0000至U+FFFF),包含了控制符、拉丁文,中、日、韓等絕大多數國際字符,但並非全部,最多見的就算如今手機端經常使用的表情字符 emoji和一些不經常使用的漢字,這些須要四個字節才能編碼出來。.net

具體解決方法操做

修改 /etc/mysql/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
init_connect='SET NAMES utf8mb4'

重啓數據庫,檢查變量

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

必須保證下面幾個變量是 utf8mb4

系統變量 描述
character_set_client 客戶端來源數據使用的字符集
character_set_connection 鏈接層字符集
character_set_database 當前選中數據庫的默認字符集
character_set_results 查詢結果字符集
character_set_server 默認的內部操做字符集

將數據庫 和 已經建好的表也轉換成 utf8mb4

ALTER DATABASE database_name CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; # 更改數據庫編碼 
ALTER TABLE table_name CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; # 更改表編碼
ALTER TABLE table_name CHANGE column_name VARCHAR(191) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;  # 更改列的編碼

查詢字符集編碼設計

show create database fangdai_CMS; # 查詢數據庫編碼
show create table t_member; # 查詢表編碼
show full columns from t_member; # 查詢全部表字段編碼

數據庫鏈接配置

添加 characterEncoding=utf8 會被自動識別爲 utf8mb4 ;autoReconnect=true 參數必須添加。

參考連接

本文由 YP小站 發佈!
相關文章
相關標籤/搜索