mysql utf8多位元組支援
Incorrect string value: '\xF0\x9F\x92\x83' for column 'content' at row 1
最近專案中遭遇了這個SQL/">MySQL的報錯資訊,具體情境是這樣的:
1. MySQL資料表charset=utf8,content欄位型別 longtext
2. 插入資料如下(簡化版): INSERT INTO tb_article(content) VALUES (':dancer:');
3. 這個奇怪的符號是從網上爬取的文章內容中的一個emoji,需要插入到mysql文章資訊表中
網上查到的資料給的解決方案是將 mysql 表的編碼調整為 utf8-mb4,這樣使mysql能夠儲存長度為4個位元組的字元,再次執行類似的插入操作就不會報錯了。 然後就產生了幾個問題:
1. mysql為什麼不支援4位元組字元?
2. mysql中的utf8和utf8-mb4分別是什麼?
3. utf-8編碼是怎麼處理多位元組字元的?
對於問題1和2下面有一段簡短的解釋,摘抄自網路:
MySQL資料庫的 “utf8”並不是真正概念裡的 UTF-8。 MySQL中的“utf8”編碼只支援最大3位元組每字元。真正的大家正在使用的UTF-8編碼是應該能支援4位元組每個字元。 MySQL的開發者沒有修復這個bug。他們在2010年增加了一個變通的方法:一個新的字符集“utf8mb4” 當然,他們並沒有對外公佈(可能因為這個bug有點尷尬)。現在很多指南推薦使用者使用“utf8”其實都錯了。
簡單的說: MySQL中的 “utf8mb4” 才是 真正意義上的“UTF-8”。 MySQL的“utf8”是個“特殊的字元編碼”。這種編碼很多Unicode字元儲存不了。
轉載處 : https://www.jianshu.com/p/ab9aa8d4df7d?openInApp=1
看完這個解釋之後應該有人會想吐槽mysql對utf-8的支援吧,不過這個解釋又引入了一個新的問題:
4. Unicode又是什麼編碼?
所以,我們現在有兩個問題了,問題3和問題4,然而這兩個問題其實就是字符集編碼的問題,如果弄明白了字元編碼,這兩個問題就明白了,所以我們還剩下一個終極問題:
1024. 計算機如何處理字元編碼??
為了搞明白這個問題,我谷歌了一篇很經典的文章,介紹了計算機字元編碼的來龍去脈,不過這篇文章是英文的,我把它翻譯成中文,由於本人英文水平有限,如果有翻譯錯誤的地方,請見諒!
譯文地址:戳我
最後,我們來給問題3和4定義答案。
問題3:utf-8編碼是怎麼處理多位元組字元的?
對於UTF-8來說,其實它定義了一套編碼規則,簡述如下:
UTF-8規定:如果一個字元只需要一個位元組儲存,則它的最高位規定為0,其餘7位儲存字元的二進位制表示(也就是ASCII碼);如果需要超過一個位元組儲存,那麼它的第一個位元組的高位中連續1的個數表示了總共佔用的位元組個數,其他各位元組最高2位固定為10。可以檢視文章 附圖3 就是UTF-8的編碼規則。
問題4:Unicode又是什麼編碼?
其實讀完文章我們就會發現,Unicode其實並不是一種編碼,它只是一個規範而已:它給每一個字元對應了一個唯一的數字,也就是 U+ 碼,相容了所有平臺、裝置、應用和語言。像ASCII、UCS-2、UTF-8、UTF-16這些才被稱為字元編碼,當記憶體中的Unicode字元需要被儲存到檔案或者要在計算機之間傳輸的時候,需要使用這些編碼中的某一個把字串編碼成相應的二進位制,再次讀入記憶體的時候又會按照同樣的編碼格式轉換成Unicode格式,所以大部分字元編碼都是遵循了Unicode規範的。
-------------------------
* 附圖1 : ASCII 字元編碼表

* 附圖2: OEM 字元編碼表(擴充了ASCII,共256個字元)

* 附圖3: UTF-8字元編碼規則

===========================================
Thanks For Reading ~~~