MySQL的客戶端可以分為兩種:一種就是用C語言寫的官方客戶端——MySQL命令程序;一種就是平常程序員使用JDBC等connector API寫成的客戶端。這裡只討論第一種。
MySQL命令程序在Windows和Linux系統中關於字符編碼處理的部分並不等效,下圖是Windows系統的客戶端字符編碼轉換邏輯:
其中的三個character變量存在於服務器上,而charset_info存在於客戶端。
當客戶端啟動連接到服務器時,客戶端將根據配置參數設置charset_info為指定編碼,同時通知服務器讓服務器把三個character變量設置為相同編碼。
由於在Windows平台上MySQL程序在讀取控制台時使用了Unicode Console Read API,所以程序從控制台獲取的原始字符串實際上是UTF16編碼,所以這裡的“操作系統編碼”並不是Windows通常的GBK,而應該看做UTF16。
下圖是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客戶端查詢時:如果Windows客戶端也想看到正確的結果,那就要故意錯誤地配置:
執行命令charset utf8,這會將charset_info和三個服務器character都設置為UTF8;執行命令set names gbk,這只會將三個服務器character設置為GBK;現在select,結果看上去不再亂碼了。