1. 程式人生 > >記一個Emoji造成的資料庫插入異常

記一個Emoji造成的資料庫插入異常

前提

這次仍然是在我的日報系統上遇到的異常崩潰,關於日報系統的簡要說明請參閱《記一次重構》.


異常資訊

Incorrect string value: ‘\xF0\x9F\x8C\xB8’ for column ‘Content’ at row 49
就是說在第49行的Content這一列插入了不正確的字串值\xF0\x9F\x8C\xB8


問題所在

這個問題倒是很好查,看來很多人都遇到過。簡而言之,問題在於向資料庫中插入了emoji表情。

然而問題並不是下面這種圖片格式的Emoji造成的:
Emoji
因為我在解析HTML時會過濾掉<img>標籤。

又經過一番搜尋和驗證,我發現瞭如下圖的這種東西:
文字Emoji
表面上看,只是和上面的Emoji風格不同,實際上另有玄機!!!


真相——文字格式的Emoji

我從網站上覆制了這些Emoji的一部分放到文字文件裡,想看看這些東西是不是圖片(圖片是不能複製進文字文件的),結果看到了驚掉下巴的東西:
文字格式的Emoji
沒錯,這些是上述那些看似彩色圖片的Emoji的真身,文字格式。


原因

那麼,既然這種東西也算是一個一個的字元,為什麼會出現資料庫插入異常呢?
原因在於:

普通的字串或者表情都是佔位3個位元組,所以utf8足夠用了,但是移動端的表情符號佔位是4個位元組,普通的utf8就不夠用了,為了應對無線網際網路的機遇和挑戰、避免 emoji 表情符號帶來的問題、涉及無線相關的 MySQL 資料庫建議都提前採用utf8mb4

字符集,這必須要作為移動網際網路行業的一個技術選型的要點。[1]

總之,這種字元存在於擴充套件之後的每個字元佔4個位元組的utf8mb4字符集中,轉換為每個字元為3個位元組的utf8就出錯了。

關於utf8mb4,請移步《淺談MySQL中utf8和utf8mb4的區別》


解決方案

根據查到的解決方案,親測有效但是描述上有錯誤,我再贅述一下。

第一步——修改MySQL配置

①開啟mysql的配置檔案,windows下的為my.ini(linux下的為my.cnf);
②找到[client],在下面新增一行
default-character-set = utf8mb4


③找到[mysqld],在下面新增兩行
character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci
④找到[mysql],在下面新增一行
default-character-set = utf8mb4
特別要注意的是,小心不要把這些寫在以#開頭的註釋裡。

第二步——修改欄位的字符集

在資料庫中,修改相應欄位(我這裡是text型別的Content欄位)的字符集為utf8mb4,排序規則為utf8mb4_general_ci
修改字符集

第三步——修改程式碼中資料庫連線字串

去掉資料庫連線字串中的?characterEncoding=utf-8

因為怕出現漢字亂碼的問題,我就沒有做這一步試了一下,親測是可以的。因此這一步不像網上說的必須要做,視情況而定。


後記

後來查明,是一位同學的日報中出現了這個:
導致崩潰的元凶
我問他的時候,他自己都沒有意識到發了這個東西過來。可能是誤觸了輸入法提供的這個吧。


  1. 摘自《【Mysql】儲存emoji表情報錯(Incorrect string value: ‘\xF0\x9F\x98\x82\xF0\x9F…’)的解決方案》 ↩︎