mysql字符轉化以及亂碼原因

MySQL 技術 ITPUB 2017-03-27

mysql中存入數據時發生的編碼轉換過程:

1、在終端(Terminal,可以是bash窗口,也可以是客戶端工具如navicat)中輸入,輸入的內容由Terminal根據其自己的字符進行編碼。

2、經Terminal編碼後的二進制流被傳輸到mysql server。mysql server(mysql engine)根據參數character_set_client的字符設置來對該二進制流進行解碼。

3、解碼之後,mysql server再次根據目的表,即table的字符集來判斷是否需要字符編碼轉換。如果character_set_client的字符設置和table定義時的character設置一致,則無需字符編碼轉換。否則進行轉換,然後將轉換後的二進制流存放到數據文件(file)中去。

總結:client ------> server(engine) -----> file 需要經過三次編碼,兩次編碼轉化。

mysql中取出數據時發生的編碼轉換過程:

1、從數據文件(file)中讀出二進制數據流,將該數據流根據table定義時的character設置來進行解碼。

2、在用table character對二級制數據流進行解碼之後,在mysql engine(mysql server)中,需要根據參數character_set_client的字符集設置對解碼後的數據庫流再一次進行編碼,將編碼之後的二級制數據庫流傳輸到client端。

3、client端,即終端(Terminal)根據其自己的字符集編碼來展示查詢結果。

總結: file ------> server(engine) -----> client 需要經過三次編碼,兩次編碼轉化。

可能會有些疑問,在上面的分析中,數據都是以二進制流的方式在各個節點之間流動的。那麼為什麼需要編碼轉化了?

1、client 和 server(engine) 之間的轉換,或者說編解碼是為了對傳進來的二進制流做語法和詞法解析,否則你不會知道傳進來的是insert還是update。

2、file 和 server(engine) 之間的轉換是為了在從數據文件讀入數據後,在存儲引擎內部進行字符級別的操作。

經過以上分析,應該很快發現導致亂碼出現的原因是有以下幾種:

1、數據在存入的時候和取出的時候,編碼不一致。比如存入時用的utf8,取出時用的GBK。

2、編碼轉換不是無損編碼轉換導致亂碼出現。比如clien是utf8,mysql server中的character_set_client設置為gbk,表結構的字符集設置為utf8。這裡會有兩次編碼轉化,client到server時,utf8要轉為gbk,然後server到file時,gbk要轉為utf8。由於gbk到utf8是有損編碼轉化,導致了亂碼出現。

無損編碼轉換:假設我們要把用編碼A表示的字符X,轉化為編碼B的表示形式,而編碼B的字形集中並沒有X這個字符,那麼此時我們就稱這個轉換是有損的。

但不是任何兩種字符集編碼之間的轉換都是有損,轉換是否有損取決於以下幾點:

------被轉換的字符是否同時在兩個字符集中

------標字符集是否能夠對不支持字符,保留其原有表達形式。(比如latin1在遇到自己無法表示的字符時,會保留原字符集的編碼數據,並跳過忽略該字符進而處理後面的數據。)

因此只要客戶端,MySQL Server的character-set-client,table charset的三個字符集完全一致就可以保證一定不會有亂碼出現了。

相關推薦

推薦中...