mysql字元轉化以及亂碼原因
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的三個字符集完全一致就可以保證一定不會有亂碼出現了。
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的三個字符集完全一致就可以保證一定不會有亂碼出現了。
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29734436/viewspace-2137629/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- MySQL亂碼的幾種原因MySql
- 關於Oracle字元亂碼?Oracle字元
- mysql中的(字元)轉換函式以及排序問題。MySql字元函式排序
- MySQL亂碼MySql
- 關於ORACLE和MYSQL中文字元亂碼的根源剖析OracleMySql字元
- mysql 插入中文亂碼解決方案 轉MySql
- mysql中文亂碼MySql
- Oracle11g字元亂碼解決Oracle字元
- oracle字元亂碼問題的解決Oracle字元
- 中文字元亂碼的解決字元
- ubuntu字元介面的亂碼問題Ubuntu字元
- Ubuntu 字元介面中文亂碼問題Ubuntu字元
- 關於JS裡的字元表情亂碼JS字元
- mysql亂碼問題MySql
- Serv-U漏洞以及原因分析(轉)
- MySQL的跳脫字元“” (轉)MySql字元
- javascript 字元轉換為ascii碼,ascii碼轉換為字元JavaScript字元ASCII
- 程式設計入門之字元編碼與亂碼程式設計字元
- Linux下修改MySQL資料庫字元編碼為UTF-8解決中文亂碼LinuxMySql資料庫字元
- PDF複製亂碼 -- 原因及解決方案
- mysql 亂碼為之奈何?MySql
- MySQL解決中文亂碼MySql
- 字元編碼轉換字元
- Oracle 中文字元及中文亂碼判斷Oracle字元
- 字元顯示亂碼問題處理辦法字元
- 生僻字顯示?的字元亂碼解決字元
- Mysql資料庫亂碼出現的各個階段以及對應方法MySql資料庫
- 【MySQL】常見slave 延遲原因以及解決方法MySql
- mysql 字符集亂碼探究MySql
- mysql字符集與亂碼MySql
- MySQL 中字元編碼問題MySql字元
- MySQL字元編碼設定方法MySql字元
- MySQL 索引原理以及優化MySql索引優化
- 【MySQL】order by 原理以及優化MySql優化
- Linux下刪除亂碼或特殊字元檔案Linux字元
- oracle中匯入dmp字元亂碼分析和解決方案Oracle字元
- 求教:網頁每隔一定字元出現亂碼。網頁字元
- SpringBoot整合Redis亂碼原因及解決方案Spring BootRedis