一次 emoji 導致的 mysql 插入異常排查

問題

通過 jdbc 向數據庫中插入數據時,由於字段值有 emoji。導致錯誤:
Caused by: java.sql.SQLException: Incorrect string value: '\xF0\xA0\xBB\xB8\xE5\x90...' for column 'address' at row 1

  • 環境

庫本身的字符集設置爲 utf8。
但是 character_set_client,character_set_connection,character_set_results 均爲 utf8mb4。
utf8mb4 是 utf8 的超集(參考:https://blog.csdn.net/vsiryxm/article/details/82919643

MySQL [(none)]> show variables like 'character%';
+--------------------------+---------------------------------------+
| Variable_name            | Value                                 |
+--------------------------+---------------------------------------+
| character_set_client     | utf8mb4                               |
| character_set_connection | utf8mb4                               |
| character_set_database   | utf8                                  |
| character_set_filesystem | binary                                |
| character_set_results    | utf8mb4                               |
| character_set_server     | utf8                                  |
| character_set_system     | utf8                                  |
| character_sets_dir       | /u01/mysql57_20190925/share/charsets/ |
+--------------------------+---------------------------------------+

建表語句

CREATE TABLE `detail` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `address` varchar(100) COLLATE utf8mb4_bin NOT NULL DEFAULT '' COMMENT '地址',
) ENGINE=InnoDB AUTO_INCREMENT=6162 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin

可見:

  • 表本身編碼爲 utf8mb4,是支持寫入 emoji 的。
  •  character_set_client,character_set_connection,character_set_results 均爲 utf8mb4。這說明客戶端只要正常連上,不做任何字符集設置修改,就能夠寫入 emoji。

排查

  • 問題出在客戶端 jdbc 配置上。

查看 jdbc 的連接串:

connectTimeout=3000;autoReconnect=true;failOverReadOnly=false;socketTimeout=900000;rewriteBatchedStatements=true;characterEncoding=utf8

可以看到 characterEncoding=utf8 的設置。

參看 mysql 官方文檔(https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-configuration-properties.html

characterEncoding: If 'useUnicode' is set to true, what character encoding should the driver use when dealing with strings? 

而 useUnicode 默認爲 true。

可見:正是 characterEncoding=utf8 這個設置導致了 emoji 無法正確插入。

解決

1. 連接串的 characterEncoding=utf8 改成 characterEncoding=utf8mb4

或者

2. 添加 connectionInitSql 參數

connectTimeout=3000;autoReconnect=true;failOverReadOnly=false;socketTimeout=900000;rewriteBatchedStatements=true;characterEncoding=utf8;connectionInitSql=set names utf8mb4

延伸閱讀

  • mysql  jdbc 連接串中所有參數

https://dev.mysql.com/doc/connector-j/5.1/en/connector-j-reference-configuration-properties.html

  • utf8 與 utf8mb4  區別

https://blog.csdn.net/vsiryxm/article/details/82919643                 
utf8mb4 是 utf8 的超集,除了將編碼改爲utf8mb4外,不需要做其他轉換。

  • mysql 的 set names 做了什麼?

https://blog.csdn.net/justsomebody126/article/details/103728644

 

 

 

 

 

 

 

 

發佈了40 篇原創文章 · 獲贊 1 · 訪問量 3431
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章