程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> MySQL的字符編碼體系(二)——數據傳輸編碼

MySQL的字符編碼體系(二)——數據傳輸編碼

編輯:MySQL綜合教程

MySQL的字符編碼體系(二)——數據傳輸編碼


MySQL的字符編碼體系可以分成兩部分:一部分是關於數據庫服務器本身存儲數據表時如何管理字符數據的編碼;另一部分是關於客戶端與數據庫服務器傳輸數據如何編碼。上一篇MySQL的字符編碼體系(一)——數據存儲編碼討論了數據存儲編碼,本篇討論數據傳輸編碼。

MySQL的客戶端可以分為兩種:一種就是用C語言寫的官方客戶端——MySQL命令程序;一種就是平常程序員使用JDBC等connector API寫成的客戶端。這裡只討論第一種。

Windows客戶端

MySQL命令程序在Windows和Linux系統中關於字符編碼處理的部分並不等效,下圖是Windows系統的客戶端字符編碼轉換邏輯:

\

其中的三個character變量存在於服務器上,而charset_info存在於客戶端。
當客戶端啟動連接到服務器時,客戶端將根據配置參數設置charset_info為指定編碼,同時通知服務器讓服務器把三個character變量設置為相同編碼。

數據傳輸流程

客戶端從控制台標准輸入讀取一行命令文本,其編碼為操作系統編碼;客戶端將命令從系統編碼轉碼為客戶端charset_info變量設定的編碼;客戶端將命令文本發送給服務器;服務器把收到的文本解碼為character_set_client編碼,這個編碼通常與客戶端charset_info一致;服務器把命令文本轉碼為character_set_connection;服務器執行命令,產生結果;將結果轉碼為character_set_results發送給客戶端;客戶端把收到的結果解碼為charset_info編碼,這個編碼通常與character_set_results一致;客戶端將結果轉碼為操作系統編碼,輸出到控制台標准輸出。

由於在Windows平台上MySQL程序在讀取控制台時使用了Unicode Console Read API,所以程序從控制台獲取的原始字符串實際上是UTF16編碼,所以這裡的“操作系統編碼”並不是Windows通常的GBK,而應該看做UTF16。

Linux客戶端

下圖是Linux系統中的MySQL客戶端程序字符編碼轉換邏輯:

vcyoTXlTUUy/zbuntsuy6dGvzazSu7j2se21w7W9tcTItMrHwtLC66GjPGJyPgq/ydLU1eLR+cSjxOLJz8r2tcTH6b/2o7o8YnI+CrS0vajSu7j2se2jrMbk1tDWu7D8uqzSu7j2R0JL19a3+7Su19a2zrrNVVRGONfWt/u0rtfWts6ho0xpbnV41tDG9LavTXlTUUzBrL3Ttb3K/b7dv+K3/s7xxvejrL2rt/7O8cb3tcTI/bj2Y2hhcmFjdGVyseTBv7TTxKzIz7XEVVRGONDeuMTOqkdCS6Gjz/LK/b7dv+Ky5cjr1tDOxMr9vt2jrMGivLRzZWxlY3SjrL3hufvO3tLss6OjujwvcD4KPHA+PGltZyBzcmM9"http://www.2cto.com/uploadfile/Collfiles/20140714/2014071409163740.png" alt="\">

但是使用Windows的MySQL客戶端查詢時,結果卻是亂碼:

\

亂碼分析

結合前面的數據傳輸流程,就能知道問題出在什麼地方:

客戶端從終端讀取了一行utf8編碼(Linux默認)的命令文本,忽略charset_info變量,直接把文本發送給服務器;服務器因為事先的命令charset gbk把三個character變量都設置為了GBK,所以服務器認為收到的文本是GBK編碼;接下來服務器會不經過任何轉碼將文本字符串直接存入數據表中,因為數據表第一個字段也是GBK。 到這裡為止,數據表中存了一個UTF8字符串,而服務器卻當它是GBK,在同一個Linux客戶端查詢時:
表中的字符串不經過任何轉碼直接發給客戶端,因為character_set_results也是GBK;客戶端收到查詢結果後因為忽略charset_info而直接不經過轉碼輸出到終端標准輸出;終端得到的數據實際上是UTF8編碼的,所以正常輸出。 在Windows客戶端查詢時:
表中的字符串(UTF8)不經過任何轉碼直接發給客戶端,因為character_set_results也是GBK;客戶端收到查詢結果後認為是charset_info編碼(此時為GBK);客戶端把查詢結果從charset_info轉碼為UTF16,然後調用Unicode Console Write API輸出,看到亂碼。

亂碼“修復”

如果Windows客戶端也想看到正確的結果,那就要故意錯誤地配置:

執行命令charset utf8,這會將charset_info和三個服務器character都設置為UTF8;執行命令set names gbk,這只會將三個服務器character設置為GBK;現在select,結果看上去不再亂碼了。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved