MySQL的字元編碼體系(二)——資料轉送編碼,mysql資料轉送

來源:互聯網
上載者:User

MySQL的字元編碼體系(二)——資料轉送編碼,mysql資料轉送
MySQL的字元編碼體系可以分成兩部分:一部分是關於資料庫伺服器本身儲存資料表時如何管理字元資料的編碼;另一部分是關於用戶端與資料庫伺服器傳輸資料如何編碼。上一篇MySQL的字元編碼體系(一)——資料存放區編碼討論了資料存放區編碼,本篇討論資料轉送編碼。

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

Windows用戶端

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


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

資料轉送流程

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

Linux用戶端

是Linux系統中的MySQL用戶端程式字元編碼轉換邏輯:


它與Windows版的不同之處就在於,它並不把來自終端標準輸入的作業系統編碼字串強制轉換為charset_info編碼,也不會把輸出到終端的charset_info編碼結果字串強制轉換為作業系統編碼。也就是說,Linux平台的MySQL程式這時候會會忽略charset_info變數。當然,這樣一來Linux用戶端的資料轉送流程就比Windows用戶端對應地少幾步。

亂碼陷阱類比

根據Linux平台MySQL程式的這一特點,很容易產生這樣一個可能的陷阱:在Linux系統中通過MySQL用戶端向資料庫插入中文資料後,查詢結果沒有亂碼,但從配置正確的Windows平台MySQL用戶端查詢同一個表得到的卻是亂碼。
可以這樣類比上述的情況:
建立一個表,其中只包含一個GBK字串欄位和UTF8字串欄位。Linux中啟動MySQL串連到資料庫伺服器,將伺服器的三個character變數從預設的UTF8修改為GBK。向資料庫插入中文資料,立即select,結果無異常:


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


亂碼分析

結合前面的資料轉送流程,就能知道問題出在什麼地方:

到這裡為止,資料表中存了一個UTF8字串,而伺服器卻當它是GBK,在同一個Linux用戶端查詢時:
在Windows用戶端查詢時:
亂碼“修複”

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



mysql資料庫表裡,中文亂碼,應該選哪種編碼?

資料庫中關於字元集的種類有很多,個人建議,資料庫字元集盡量使用utf8(utf-8),以使你的資料能很順利的實現遷移,因為utf8字元集是目前最適合於實現多種不同字元集之間的轉換的字元集,儘管你在命令列工具上無法正確查看資料庫中的內容,我依然強烈建議使用utf8作為預設字元集.如果你想使用gb2312編碼,那麼建議你使用latin1作為資料表的預設字元集,這樣就能直接用中文在命令列工具中插入資料,並且可以直接顯示出來.而不要使用gb2312或者gbk等字元集,如果擔心查詢排序等問題,可以使用binary屬性約束 對編程有影響的主要是用戶端字元集和資料庫字元集(還有一個伺服器字元集,不知道幹什麼用的), 資料庫中常用的操作就是儲存資料和讀取資料,在這過程中,亂不亂碼和資料庫字元集貌似沒有什麼關係。我們只要保證寫入時選擇的字元集和讀取時選擇的字元集一致,即只需保證兩次操作的用戶端字元集一致即可。
在MySQL的用戶端上執行一次查詢的過程一般是,在用戶端的提示符後面輸入一條SQL語句,斷行符號,然後終端顯示出查詢的結果。這個過程中,只有終端和三個MySQL的系統變數指定了正確的字元集,才能保證我們將一個正確的SQL語句送到伺服器,然後伺服器返回正確的結果,並且在終端正確顯示。
三個MySQL的系統變數是:
1. character_set_client,終端字元集,告訴Server用戶端提交的SQL語句的編碼格式
2. character_set_connection,串連字元集,是伺服器翻譯SQL語句時用到的編碼格式
3. character_set_results,返回的結果集的字元集,是伺服器返回結果集之前把結果集轉換成的編碼格式
在MySQL終端通過執行命令 show variables like ‘char%’ 可以查看這幾個變數的值。這三個變數通常都設定為同一種字元集,用命令set names [charset name]就可以修改這三個變數的值。一般來說,只要你設定了能夠表示你的資料的字元集,你查詢的結果都可以在終端正確顯示。
舉個例子,使用的表t1是utf8編碼,表中的欄位c1繼承了這個編碼,表建立如下
mysql> create table t1 ( c1 text not null ) character set utf8;
用的字元是漢字“範”,gbk編碼為B7 B6,utf8編碼為E8 8C 83
用下面的SQL語句插入資料
mysql> insert into t1 values( ‘範’);
a)如果終端設定為utf8,並且執行了 set names utf8,那麼插入到資料庫中的就是“範”這個字的utf8編碼,這個過程中MySQL不需要做編碼轉換。寫入資料庫的內容可以通過執行 select hex( c1 ) from t1 得到資料的十六進位編碼來驗證。

b)如果終端設定為 utf8,並且執行了set names gbk,那麼執行完這個插入操作後,寫入的位元據是E9 91 BC,這是“漢字“鑼”的utf8編碼。這是因為,終端輸入的“範”用的是utf8編碼,而伺服器以為終端發送過來的內容是gbk編碼,所以在向t1表中插入的時候進行了一次gbk到utf8的轉換,結果當然是錯誤的。

c)如果終端設定為gbk,並且執行了set names gbk,那麼執行完插入操作後,寫入t1的依然是“範”這個字的utf8編碼。插入過程中,終端輸入的是“範”的gbk編碼B7 B6,伺服器被告知終端發......餘下全文>>
 
怎查看mysql自訂資料庫的編碼字元集

如果你用Navicat Premium軟體管理的話,直接點中資料庫名按右鍵查看字元集即可!
若你是用PHPADMIN的話,點資料庫名,右上面就會顯字元集;
 

相關文章

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.