歡迎來(lái)到深圳市志博科技有限公司網站!
您當前的(de)位置:深圳APP開發 > 新聞資訊 > APP開發資訊 >
人(rén)
已閱讀

APP開發時(shí)關于mysql數據庫UTF8編碼的(de)問題

來(lái)源:lexintech.com       發布時(shí)間:2019-05-17
目前在APP開發中我們常用(yòng)的(de)數據庫是mysql,但是我們在使用(yòng)mysql的(de)時(shí)候,關于utf-8編碼的(de)問題需要注意。MySQL 的(de)“utf8”實際上不是真正的(de) UTF-8。“utf8”隻支持每個(gè)字符最多(duō)三個(gè)字節,而真正的(de) UTF-8 是每個(gè)字符最多(duō)四個(gè)字節。MySQL 一直沒有修複這(zhè)個(gè) bug,他(tā)們在 2010 年發布了(le)一個(gè)叫作“utf8mb4”的(de)字符集,繞過了(le)這(zhè)個(gè)問題。
APP開發時(shí)關于mysql數據庫UTF8編碼的(de)問題
我們都知道,計算(suàn)機使用(yòng) 0 和(hé) 1 來(lái)存儲文本。比如字符“C”被存成“01000011”,那麽計算(suàn)機在顯示這(zhè)個(gè)字符時(shí)需要經過兩個(gè)步驟:
計算(suàn)機讀取“01000011”,得(de)到數字 67,因爲 67 被編碼成“01000011”。
計算(suàn)機在 Unicode 字符集中查找 67,找到了(le)“C”。
同樣的(de):
我的(de)電腦(nǎo)将“C”映射成 Unicode 字符集中的(de) 67。
我的(de)電腦(nǎo)将 67 編碼成“01000011”,并發送給 Web 服務器。
幾乎所有的(de)網絡應用(yòng)都使用(yòng)了(le) Unicode 字符集,因爲沒有理(lǐ)由使用(yòng)其他(tā)字符集。
Unicode 字符集包含了(le)上百萬個(gè)字符。最簡單的(de)編碼是 UTF-32,每個(gè)字符使用(yòng) 32 位。這(zhè)樣做(zuò)最簡單,因爲一直以來(lái),計算(suàn)機将 32 位視爲數字,而計算(suàn)機最在行的(de)就是處理(lǐ)數字。但問題是,這(zhè)樣太浪費空間了(le)。
UTF-8 可(kě)以節省空間,在 UTF-8 中,字符“C”隻需要 8 位,一些不常用(yòng)的(de)字符,比如“”需要 32 位。其他(tā)的(de)字符可(kě)能使用(yòng) 16 位或 24 位。一篇類似本文這(zhè)樣的(de)文章(zhāng),如果使用(yòng) UTF-8 編碼,占用(yòng)的(de)空間隻有 UTF-32 的(de)四分(fēn)之一左右。
 
爲什(shén)麽 MySQL 開發者會讓“utf8”失效?我們或許可(kě)以從提交日志中尋找答(dá)案。
MySQL 從 4.1 版本開始支持 UTF-8,也(yě)就是 2003 年,而今天使用(yòng)的(de) UTF-8 标準(RFC 3629)是随後才出現的(de)。
舊(jiù)版的(de) UTF-8 标準(RFC 2279)最多(duō)支持每個(gè)字符 6 個(gè)字節。2002 年 3 月(yuè) 28 日,MySQL 開發者在第一個(gè) MySQL 4.1 預覽版中使用(yòng)了(le) RFC 2279。
2002 年,MySQL 做(zuò)出了(le)一個(gè)決定:如果用(yòng)戶可(kě)以保證數據表的(de)每一行都使用(yòng)相同的(de)字節數,那麽 MySQL 就可(kě)以在性能方面來(lái)一個(gè)大(dà)提升。爲此,用(yòng)戶需要将文本列定義爲“CHAR”,每個(gè)“CHAR”列總是擁有相同數量的(de)字符。如果插入的(de)字符少于定義的(de)數量,MySQL 就會在後面填充空格,如果插入的(de)字符超過了(le)定義的(de)數量,後面超出部分(fēn)會被截斷。
MySQL 開發者在最開始嘗試 UTF-8 時(shí)使用(yòng)了(le)每個(gè)字符 6 個(gè)字節,CHAR(1) 使用(yòng) 6 個(gè)字節,CHAR(2) 使用(yòng) 12 個(gè)字節,并以此類推。
應該說,他(tā)們最初的(de)行爲才是正确的(de),可(kě)惜這(zhè)一版本一直沒有發布。但是文檔上卻這(zhè)麽寫了(le),而且廣爲流傳,所有了(le)解 UTF-8 的(de)人(rén)都認同文檔裏寫的(de)東西。
不過很顯然,MySQL 開發者或廠商擔心會有用(yòng)戶做(zuò)這(zhè)兩件事:
使用(yòng) CHAR 定義列(在現在看來(lái),CHAR 已經是老古董了(le),但在那時(shí),在 MySQL 中使用(yòng) CHAR 會更快(kuài),不過從 2005 年以後就不是這(zhè)樣子了(le))。
将 CHAR 列的(de)編碼設置爲“utf8”。
我的(de)猜測是 MySQL 開發者本來(lái)想幫助那些希望在空間和(hé)速度上雙赢的(de)用(yòng)戶,但他(tā)們搞砸了(le)“utf8”編碼。
所以結果就是沒有赢家。那些希望在空間和(hé)速度上雙赢的(de)用(yòng)戶,當他(tā)們在使用(yòng)“utf8”的(de) CHAR 列時(shí),實際上使用(yòng)的(de)空間比預期的(de)更大(dà),速度也(yě)比預期的(de)慢(màn)。而想要正确性的(de)用(yòng)戶,當他(tā)們使用(yòng)“utf8”編碼時(shí),卻無法保存像“”這(zhè)樣的(de)字符。
在這(zhè)個(gè)不合法的(de)字符集發布了(le)之後,MySQL 就無法修複它,因爲這(zhè)樣需要要求所有用(yòng)戶重新構建他(tā)們的(de)數據庫。最終,MySQL 在 2010 年重新發布了(le)“utf8mb4”來(lái)支持真正的(de) UTF-8。
 
所以,如果你在使用(yòng) MySQL 或 MariaDB,不要用(yòng)“utf8”編碼,改用(yòng)“utf8mb4”。
 
APP開發 網站開發 産品設計 微信公衆号 APP開發公司 用(yòng)戶體驗 APP運營 微信小程序 産品經理(lǐ) 網站設計