色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

MySQL巨坑:永遠不要在MySQL中使用UTF-8!!

數據分析與開發 ? 來源:數據分析與開發 ? 2023-08-21 14:47 ? 次閱讀

最近我遇到了一個bug,我試著通過Rails在以“utf8”編碼的MariaDB中保存一個UTF-8字符串,然后出現了一個離奇的錯誤:

Incorrect string value: ‘e <…’ for column ‘summary’ at row 1

我用的是UTF-8編碼的客戶端,服務器也是UTF-8編碼的,數據庫也是,就連要保存的這個字符串“ <…”也是合法的UTF-8。

問題的癥結在于,MySQL的“utf8”實際上不是真正的UTF-8。

“utf8”只支持每個字符最多三個字節,而真正的UTF-8是每個字符最多四個字節。

MySQL一直沒有修復這個bug,他們在2010年發布了一個叫作“utf8mb4”的字符集,繞過了這個問題。

當然,他們并沒有對新的字符集廣而告之(可能是因為這個bug讓他們覺得很尷尬),以致于現在網絡上仍然在建議開發者使用“utf8”,但這些建議都是錯誤的。


		

簡單概括如下:

  1. MySQL的“utf8mb4”是真正的“UTF-8”。

  2. MySQL的“utf8”是一種“專屬的編碼”,它能夠編碼的Unicode字符并不多。

我要在這里澄清一下:所有在使用“utf8”的MySQL和MariaDB用戶都應該改用“utf8mb4”,永遠都不要再使用“utf8”。

那么什么是編碼?什么是UTF-8?

我們都知道,計算機使用0和1來存儲文本。比如字符“C”被存成“01000011”,那么計算機在顯示這個字符時需要經過兩個步驟:

  1. 計算機讀取“01000011”,得到數字67,因為67被編碼成“01000011”。

  2. 計算機在Unicode字符集中查找67,找到了“C”。

同樣的:

  1. 我的電腦將“C”映射成Unicode字符集中的67。

  2. 我的電腦將67編碼成“01000011”,并發送給Web服務器。

幾乎所有的網絡應用都使用了Unicode字符集,因為沒有理由使用其他字符集。

Unicode字符集包含了上百萬個字符。最簡單的編碼是UTF-32,每個字符使用32位。這樣做最簡單,因為一直以來,計算機將32位視為數字,而計算機最在行的就是處理數字。但問題是,這樣太浪費空間了。

UTF-8可以節省空間,在UTF-8中,字符“C”只需要8位,一些不常用的字符,比如“”需要32位。其他的字符可能使用16位或24位。一篇類似本文這樣的文章,如果使用UTF-8編碼,占用的空間只有UTF-32的四分之一左右。

MySQL的“utf8”字符集與其他程序不兼容,它所謂的“”,可能真的是一坨……

MySQL簡史

為什么MySQL開發者會讓“utf8”失效?我們或許可以從提交日志中尋找答案。

MySQL從4.1版本開始支持UTF-8,也就是2003年,而今天使用的UTF-8標準(RFC 3629)是隨后才出現的。

舊版的UTF-8標準(RFC 2279)最多支持每個字符6個字節。2002年3月28日,MySQL開發者在第一個MySQL 4.1預覽版中使用了RFC 2279。

同年9月,他們對MySQL源代碼進行了一次調整:“UTF8現在最多只支持3個字節的序列”。

是誰提交了這些代碼?他為什么要這樣做?這個問題不得而知。在遷移到Git后(MySQL最開始使用的是BitKeeper),MySQL代碼庫中的很多提交者的名字都丟失了。2003年9月的郵件列表中也找不到可以解釋這一變更的線索。

不過我可以試著猜測一下。

2002年,MySQL做出了一個決定:如果用戶可以保證數據表的每一行都使用相同的字節數,那么MySQL就可以在性能方面來一個大提升。為此,用戶需要將文本列定義為“CHAR”,每個“CHAR”列總是擁有相同數量的字符。如果插入的字符少于定義的數量,MySQL就會在后面填充空格,如果插入的字符超過了定義的數量,后面超出部分會被截斷。

MySQL開發者在最開始嘗試UTF-8時使用了每個字符6個字節,CHAR(1)使用6個字節,CHAR(2)使用12個字節,并以此類推。

應該說,他們最初的行為才是正確的,可惜這一版本一直沒有發布。但是文檔上卻這么寫了,而且廣為流傳,所有了解UTF-8的人都認同文檔里寫的東西。

不過很顯然,MySQL開發者或廠商擔心會有用戶做這兩件事:

  1. 使用CHAR定義列(在現在看來,CHAR已經是老古董了,但在那時,在MySQL中使用CHAR會更快,不過從2005年以后就不是這樣子了)。

  2. 將CHAR列的編碼設置為“utf8”。

我的猜測是MySQL開發者本來想幫助那些希望在空間和速度上雙贏的用戶,但他們搞砸了“utf8”編碼。

所以結果就是沒有贏家。那些希望在空間和速度上雙贏的用戶,當他們在使用“utf8”的CHAR列時,實際上使用的空間比預期的更大,速度也比預期的慢。而想要正確性的用戶,當他們使用“utf8”編碼時,卻無法保存像“”這樣的字符。

在這個不合法的字符集發布了之后,MySQL就無法修復它,因為這樣需要要求所有用戶重新構建他們的數據庫。最終,MySQL在2010年重新發布了“utf8mb4”來支持真正的UTF-8。


		

為什么這件事情會讓人如此抓狂

因為這個問題,我整整抓狂了一個禮拜。我被“utf8”愚弄了,花了很多時間才找到這個bug。但我一定不是唯一的一個,網絡上幾乎所有的文章都把“utf8”當成是真正的UTF-8。

“utf8”只能算是個專有的字符集,它給我們帶來了新問題,卻一直沒有得到解決。

總結

如果你在使用MySQL或MariaDB,不要用“utf8”編碼,改用“utf8mb4”。這里(https://mathiasbynens.be/notes/mysql-utf8mb4#utf8-to-utf8mb4)提供了一個指南用于將現有數據庫的字符編碼從“utf8”轉成“utf8mb4”。


	
			

聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 編碼
    +關注

    關注

    6

    文章

    957

    瀏覽量

    54911
  • 數據庫
    +關注

    關注

    7

    文章

    3845

    瀏覽量

    64592
  • MySQL
    +關注

    關注

    1

    文章

    829

    瀏覽量

    26675

原文標題:MySQL 巨坑:永遠不要在 MySQL 中使用 UTF-8!!

文章出處:【微信號:DBDevs,微信公眾號:數據分析與開發】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    labview 在mysql數據庫存中文亂碼問題

    誰知道labview 在mysql數據庫存中文怎么存,mysql 數據庫已經設置utf-8編碼了,添加中文進去還是亂碼!
    發表于 12-06 20:23

    樹莓派MYSQL安裝【附離線安裝mysql

    character-set-server=utf8 collation-server=utf8_general_ci CTRL+X保存(或者是輸入!wq),然后sudo reboot重啟一下樹莓派 進入mysql,使用show
    發表于 03-03 12:14

    0基礎學Mysql:mysql入門視頻教程!

    DDL語句第5節 SQL語句之DML語句和DCL第6節 SQL語句課堂實踐精確授權優先第7節 復習MySQL基礎第8節 破解MariaDB 5.5 root密碼第9節 MySQL備份的分類和備份的兩大
    發表于 07-08 10:51

    怎么在MDB中將編碼設置為UTF-8

    是否有一種方法將編碼設置為MDB中的UTF-8。我在Ubuntu/PIC18/XC8編譯器上運行我的測試代碼,預處理失敗了,在UTF-8中使用了一個無效的字節序列。一些外來字符的存在導
    發表于 10-25 16:51

    如何將文件編碼更改為UTF-8

    HII正在對我的項目本地化,需要使用UTF-8編碼的字符串。我有一切工作代碼,但在編輯器中,字符串顯示,如果編碼的ANSI拉丁代碼頁。我了解到,在開始新項目時可以選擇UTF-8編碼,關于如何為現有
    發表于 07-03 10:30

    請問mysql數據庫一個漢字到底占幾個字節?

    GBK 和 UTF-8 字符集我都測試了,漢字在 MYSQL 里都占一個字節,例如一個字段 varchar (2),就能存儲兩個漢字或兩個字母或兩個數字。但我在網上搜了半天,都說 MYSQL
    發表于 06-02 14:48

    mysql中文手冊

    1 MySQL的一般的信息 1.1 什么是MySQL? 1.2 關于本手冊 1.2.1 本手冊中使用的約定 1.3 MySQL的歷史 1.4 MyS
    發表于 12-26 13:27 ?83次下載

    PHP/MySQL教程

    PHP/MySQL教程(一)  PHP/MySQL教程(二)  PHP/MySQL教程(三)  PHP/MySQL教程(四)  PHP/
    發表于 01-10 23:43 ?0次下載

    ascii和utf8的區別_ASCII編碼與UTF-8的關系

    UTF-8是一種針對Unicode的可變長度字符編碼,又稱萬國碼。由Ken Thompson于1992年創建。現在已經標準化為RFC 3629。UTF-8用1到6個字節編碼Unicode字符。ASCII是基于拉丁字母的一套電腦編碼系統,主要用于顯示現代英語和其他西歐語言。
    的頭像 發表于 01-30 13:34 ?3w次閱讀
    ascii和<b class='flag-5'>utf8</b>的區別_ASCII編碼與<b class='flag-5'>UTF-8</b>的關系

    PHP和UTF-8亂碼問題的解決方法資料分析

    PHP亂碼問題,UTF-8亂碼問題比較常見,通過下面的方法基本上就可以解決php亂碼問題了,確實總結的不錯。
    發表于 02-28 17:59 ?5次下載
    PHP和<b class='flag-5'>UTF-8</b>亂碼問題的解決方法資料分析

    從ASCII碼-&gt;Unicode-&gt; UTF-8歷史變遷,及其差異

    從ASCII碼->Unicode->UTF-8歷史變遷,及其差異
    的頭像 發表于 02-27 15:56 ?2598次閱讀

    MySQLutf8utf8mb4有什么區別

    MySQL在5.5.3之后增加了這個utf8mb4的編碼,mb4就是most bytes 4的意思,專門用來兼容四字節的unicode。
    的頭像 發表于 04-12 19:21 ?1.3w次閱讀

    為什么不建議在MySQL中使UTF-8

    Unicode 字符集包含了上百萬個字符。最簡單的編碼是 UTF-32,每個字符使用 32 位。這樣做最簡單,因為一直以來,計算機將 32 位視為數字,而計算機最在行的就是處理數字。但問題是,這樣太浪費空間了。
    的頭像 發表于 03-13 10:37 ?681次閱讀

    mysql8.0默認字符集是什么

    MySQL 8.0 默認字符集是 utf8mb4。 MySQL 8.0 是當前最新的開源關系型數據庫管理系統,由Oracle公司開發和維護。MySQL 8.0 默認字符集是
    的頭像 發表于 11-16 14:48 ?1874次閱讀

    windows服務器備份mysql腳本

    一、linux備份 使用python腳本,要求有python3和mysqldump #! /usr/bin/python36# -*- coding: utf-8 -*-import
    的頭像 發表于 01-02 09:14 ?100次閱讀
    主站蜘蛛池模板: 草699一码二码三码四码 | 甜宠溺H宝贝嗯撞PLAY啊 | 国产亚洲精品在线视频 | 失禁 调教 刺激 哭喊男男 | 日本美女论坛 | 天堂岛www| 别插我B嗯啊视频免费 | 亚洲中字幕永久在线观看 | 国产午夜免费视频片夜色 | 国产高清美女一级a毛片久久w | 国产麻豆精品传媒AV国产在线 | 空姐厕所啪啪啪 | free乌克兰性xxxxhd| 绝色娇嫩美人妻老师 | 亚洲蜜桃AV永久无码精品放毛片 | 97国产精品人妻无码免费 | 午夜国产精品视频在线 | 欧美成人无码A区在线观看免费 | 国产精品久久高潮呻吟无码 | 成人免费视频在线播放 | 老司机午夜影院试看区 | 最新国产在线视频在线 | 色偷偷爱偷偷要 | 国内精品久久久久久久999下 | 国产精品视频免费观看 | 国产在线成人一区二区三区 | 日韩欧美一级 | 久久夜色撩人精品国产 | 久久精品视在线观看85 | 男gv纯肉免费视频 | 国产综合视频在线观看一区 | 美女露出逼 | 亚洲精品久久久无码 | 中文字幕乱码一区AV久久 | 果冻传媒在线观看资源七夕 | 青柠高清在线观看完整版 | 欧美国产精品久久久乱码 | 国产人妻久久久精品麻豆 | 少妇精品久久久一区二区三区 | 国产91综合 | 国产精品7777人妻精品冫 |