記一個Emoji造成的資料庫插入異常
前提
這次仍然是在我的日報系統上遇到的異常崩潰,關於日報系統的簡要說明請參閱《記一次重構》.
異常資訊
Incorrect string value: ‘\xF0\x9F\x8C\xB8’ for column ‘Content’ at row 49
就是說在第49
行的Content
這一列插入了不正確的字串值\xF0\x9F\x8C\xB8
。
問題所在
這個問題倒是很好查,看來很多人都遇到過。簡而言之,問題在於向資料庫中插入了emoji表情。
然而問題並不是下面這種圖片格式的Emoji造成的:
因為我在解析HTML時會過濾掉<img>標籤。
又經過一番搜尋和驗證,我發現瞭如下圖的這種東西:
表面上看,只是和上面的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
因為怕出現漢字亂碼的問題,我就沒有做這一步試了一下,親測是可以的。因此這一步不像網上說的必須要做,視情況而定。
後記
後來查明,是一位同學的日報中出現了這個:
我問他的時候,他自己都沒有意識到發了這個東西過來。可能是誤觸了輸入法提供的這個吧。