最近,在項目組使用的MySQL數據庫中,插入數據出現亂碼問題,出現諸如???,或者????等字符。為了防止在
今后項目中再次出現相類似問題。在這里對于MySQL編碼問題做一個詳細的介紹并對于亂碼問題提出一些解決方案。
一. 概念介紹1.字符集(Character set)字符集是多個字符的集合,字符集種類較多,每個字符集包含的字符個數不同,常見的字符集名稱:ASCII字符集、
GB2312字符集、BIG5字符集等。對于中文文字來說,數目大,而且還分為簡體中文和繁體中文兩種不同書寫規范的文
字,故一般出現亂碼都出現在輸入中文數據的時候。常見的中文字符集:GB2312、GBK、UTF8等。
2.常見中文字符集介紹
GB2312:1980年發布,是中文信息處理的國際標準,在大陸及海外使用簡體中文的地區是強制使用的唯一中
文編碼。GB2312共收錄6763個簡體漢字、682個符號。
GBK:漢字國際擴展碼,基本上采用了原來GB2312所有的漢字及碼位,并涵蓋原Unicode中所有的漢字,總
共收錄了883個符號,21003個漢字及提供了1894個造字碼位。GBK兼容GB2312,并且簡、繁體字融于一庫。
UTF8:UTF8編碼包含全世界所有國家需要用到的字符,可在各國各種支持UTF8字符集的瀏覽器上顯示,即使用UTF8編碼,可在同一頁面中顯示多種國家的文字。
3.字符序(Collation)
字符序是指在同一字符集內字符之間的比較規則,在確定字符序后,才能在一個字符集上定義什么是等價的字符,以及字符之間的大小關系。每個字符序唯一對應一種字符集,但一個字符集可以對應多種字符序,其中有一個是默認字符序(Default Collation). MySQL中的字符序名稱遵從命名慣例:以字符序對應的字符集名稱開頭:以_ci結尾的表示大小寫不敏感、以_cs結尾的表示大小寫敏感,以_bin結尾的表示按編碼值比較。例如:在字符序“utf8_general_ci”下字符“a”和“A”是等價的。
4.MySQL的字符集支持
通過命令:show character set和show collation可以分別查看MySQL支持的字符集和排序方式。


5.關于MySQL字符集變量
     使用命令show variables like ‘character%’;可看到當前連接的所有字符集設置。
character_set_client:客戶端來源數據使用的字符集
character_set_connection:連接層字符集
character_set_database:當前選中數據庫的默認字符集
character_set_results:查詢結果字符集
character_set_server:默認的內部操作字符集
character_set_system:系統元數據(字段名等)字符集
眾所周知,MySQL對于字符集的指定可以細化到一個數據庫,一張表,一列,應該使用什么字符集。但是傳統的程序在創建數據庫和表時并沒有使用十分負責的配置,它們用的是默認的配置,那么,默認的配置從何而來呢?
(1)編譯MySQL時,指定了一個默認的字符集,這個字符集是 latin1;(2)安裝MySQL 時,可以在配置文件 (my.ini) 中指定一個默認的的字符集,如果沒指定,這個值繼承自編譯時指定的;(3)啟動mysqld 時,可以在命令行參數中指定一個默認的的字符集,如果沒指定,這個值繼承自配置文件中的配置,此時 character_set_server 被設定為這個默認的字符集;(4)當創建一個新的數據庫時,除非明確指定,這個數據庫的字符集被缺省設定為character_set_server;(5)當選定了一個數據庫時,character_set_database 被設定為這個數據庫默認的字符集;(6)在這個數據庫里創建一張表時,表默認的字符集被設定為 character_set_database,也就是這個數據庫默認的字符集;(7)當在表內設置一欄時,除非明確指定,否則此欄缺省的字符集就是表默認的字符集;
簡單的總結一下,如果什么地方都不修改,那么所有的數據庫的所有表的所有欄位的都用 latin1存儲,不過我們如果安裝 MySQL,一般都會選擇多語言支持,也就是說,安裝程序會自動在配置文件中把default_character_set設置為 UTF-8,這保證了缺省情況下,所有的數據庫的所有表的所有欄位的都用 UTF-8 存儲。
上述6個變量中,除了character_set_client,character_set_connection,character_set_results三個變量之外,其余的變量都是在安裝MySQL選擇語言時,自動設置的,一般不用特意改變。所以大部分的問題都是出在character_set_client,character_set_connection,character_set_results的不匹配上。
這三個參數的作用如下:

系統變量character_set_client:用來指定解析客戶端傳遞數據的編碼
系統變量character_set_connection:用來指定數據庫內部處理時使用的編碼
系統變量character_set_results:用來指定數據返回給客戶端的編碼方式
因此我們只要保證上述三個變量的編碼方式是一樣的,那么編碼問題就不會存在。
二. 如何修改默認字符集1.最簡單的修改方法,就是修改/etc/my.ini文件中的字符集默認配置。在[client]下添加上
default-character-set=utf8(這里用utf8舉例說明,如果想改成gbk,則該位置設置為gbk即可)
上述方法等同于執行以下3個命令
SET character_set_client =utf8
SET character_set_results =utf8
SET character_set_connection= utf8
2.在創建jdbc連接的時候使用jdbc:mysql://localhost:3306/test?characterEncoding=UTF-8&characterSetResults=UTF-8
characterEncoding=UTF-8指定了character_set_client、character_set_connection的值。
而characterSetResults=UTF-8則指定了character_set_results的值。與方法一的思路是一樣的。
3.直接使用sql命令進行修改,在命令行中輸入
SET character_set_client = utf8
SET character_set_results = utf8;
SET character_set_connection = utf8;
或者直接輸入 set Names utf8 就可以同時修改三個。
4.若使用MySQL客戶端 如Navicat之類的,則直接在new connection的時候在Encoding選項中選擇utf8 即可
還是推薦第一種方法,簡單方便,所有的后續操作都不會編碼問題。
三. 亂碼問題分析
編碼問題比較容易出現在共同開發的項目中,一般是由于小組中人員在在通過各種方式連接數據庫時,所選擇的編碼
類型不同。
Ques:數據從web端(web端使用utf8)寫入,并在web頁面中顯示正常,但在數據庫中查看卻是亂碼?
Ans:這里總共有兩個連接。 一個是通過jdbc連接的,另一個是自己從mysql客戶端建的連接用于直接查看數據庫中的
數據。亂碼的原因在于建立這兩個連接時,設置的編碼方式不同。假設,jdbc的連接是jdbc:mysql://localhost:3306/test
?characterEncoding=UTF-8&characterSetResults=UTF-8, 則意味著character_set_client,character_set_connection,
character_set_results 這三個參數都是utf8的。 即數據按照前兩個參數的編碼類型寫入數據庫,并且由于
character_set_results 也是utf8的,所以讀取時返回的字符集也是utf8的則不會出現亂碼。
此時如果自己mysql客戶端建立的連接是gbk的, 即該連接的character_set_results是gbk的, 那么通過web端utf8格式
寫入的中文字符在讀取出來時需要轉換為gbk的,那么就會出現亂碼。由于utf8的碼位遠遠超過gbk的,所以在gbk
的results看來該碼位是不能顯示的所以會顯示???。 而此時如果你通過gbk的連接輸入中文字符,則在web端頁面
會顯示????等外文字符,這是由于gbk的碼位比utf8少, 對應的gbk的碼位是可以在utf8中解析的,只是不能顯示正確
的中文字符。
四.結論
我們只要保證character_set_client,character_set_connection,character_set_results
是和你使用的客戶端編碼格式相同,即如果你的web頁面是用utf8的,那么上述三個也必
須是utf8的。如果你項目中已經出現亂碼了,那么應該在組內統一編碼格式,再對數據庫
中的數據進行重新插入。
新聞熱點
疑難解答