mysql的字元集設定眾多,從用戶端到串連到結果集,從伺服器到庫到表到列,都可以設定字元集,靈活很強大,但就是很容易出問題,如果不瞭解其機制,很容易就出現亂碼問題。
為了普度眾生,讓大家盡量在工作中少受或者不受亂碼的騷擾、困擾,這裡我結合之前其它同學在論壇的發帖,並結合自己的理解和實踐,詳細分析總結了一下,以饗各位看官。
關於字元集和亂碼的基礎知識這裡就不詳細說明了(請自行搜尋),但有一個問題需要特彆強調一下:亂碼是怎麼產生的?
這個問題相信很多同學都是模稜兩可,或者沒有認真想過,反正理解就是”字元編碼“不對導致亂碼,但沒有真正想過為什麼”字元編碼“會導致亂碼。
答案其實很簡單:“轉換導致亂碼”!
根據這個原則來判斷,各種情況就很簡單了:
1)資料傳送過程中不會導致亂碼
2)資料存放區不會導致亂碼
3)資料輸入和輸出(包括顯示)可能導致亂碼
4)資料接收和發送可能導致亂碼
更詳細的解釋:轉換導致亂碼是指本來是A字元集的資料被當成了B字元集進行解析,而不是說正確的A字元集轉換為B字元集。
例如:如下mysql字元處理機制流程圖中,mysql用戶端發送的實際上是2個gbk字元(4位元組),但character_set_connection
設定了utf8,於是mysql伺服器將收到的4位元組gbk資料按照utf8解析,得到1個中文字元+1個位元組,這時就產生亂碼了;
如果character_set_connection 設定為gbk,mysql伺服器收到資料後按照gbk解析,得到兩個正確的中文,然後再轉換為這兩個中文對應的utf8編碼,這就不會產生亂碼。)
【mysql的字元處理機制】
詳細的處理機制如:
我們類比一下一條資料從插入到讀取的處理流程,看看在整個流程中,字元集是如何輾轉騰挪的。
【插入流程】
1. 用戶端設定了自己的編碼(character_set_client),接收使用者的輸入;
2. 用戶端將使用者的輸入“轉換”成串連的編碼(character_set_connection) =====> 第一次轉換
3. 用戶端將轉換後的資料發送給伺服器; =====> 傳輸不會導致編碼轉換
4. 伺服器收到用戶端的資料,再判斷資料列的字元集,進行字元轉換 =====> 第二次轉換
5. 伺服器將資料存放區(例如磁碟) =====> 儲存不會導致編碼轉換