標籤:blog http io ar 使用 sp 檔案 資料 on
最近遇到mysql亂碼的問題,找了些資料,先儲存,後面慢慢總結自己的處理方法。
筆記:
問題環境總結:
1.前台php代碼沒有改變
2.原資料庫,所有表的都是utf8
mysql> show variables like ‘%char%‘;
+--------------------------+----------------------------------+
| Variable_name | Value |
+--------------------------+----------------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_filesystem | binary |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /pub/mysql/share/mysql/charsets/ |
+--------------------------+----------------------------------+
備份庫的編碼(mysql主從複製過來的):
mysql> show variables like ‘%char%‘;
+--------------------------+----------------------------------+
| Variable_name | Value |
+--------------------------+----------------------------------+
| character_set_client | utf8 |
| character_set_connection | utf8 |
| character_set_database | utf8 |
| character_set_filesystem | binary |
| character_set_results | utf8 |
| character_set_server | utf8 |
| character_set_system | utf8 |
| character_sets_dir | /opt/mysql/share/mysql/charsets/ |
+--------------------------+----------------------------------+
8 rows in set (0.00 sec)
另一個資料庫(資料庫三),資料完全複製的備份庫的檔案。
問題來了:
1.現有的php前台串連資料庫三所讀出來的資料都是亂碼,串連備份庫和原數庫都是正常的
2.換了一個php的環境(即前台伺服器),串連三個庫又都正常了
轉自:http://blog.csdn.net/martinkro/article/details/5352474
1 MYSQL中的字元集概念
Mysql的字元集裡有兩個概念,一個是"Character set(字元集)",另一個是"Collations"。
1.1 Collations
Collations翻成中文是"校正",在網頁開發的過程中,這個詞彙,只在Mysql裡使用,主要作用是指導Mysql對字元的比較,比如, ASCII字元集裡,Collations規定了a小於b,a等於a,以及a是否等於A之類的。通常,大家基本可以忽略Collations的存在,因為每個字元集都有一個預設的Collations,通常,使用預設的Collations就可以了。
1.2 Character set
與這對比的是,字元集是個更廣的概念,即使是Windows下普通的文字檔,也滲及到字元集的問題。不同的字元集,規定了不同的字元的編碼方式。一個 character set (字元集)是一組符號和編碼,比如,ASCII字元集,包括的字元有:數字,大小寫字母,分號、換行之類的符號,編碼方式是用一個7bit表示一個字元(A的編碼是65,b的編碼是98)。ASCII只規定了英文字母的編碼,非英文語言不能用ASCII編碼錶示,為此,不同的國家,都為自己的語言做了編碼,比如,我們國家,就有GB2312編碼。但每個國家之間的編碼不同,也存在著一些跨平台的問題,為此,一些國際化標準組織,就制定了一些國際通用的編碼,最常用的就是UTF8了。ASCII只對英文符號和英文字母做了編碼,GB2312對英文符號,英文字母,漢字做了編碼,UTF8對世界上所有的語言文字做了編碼,所以,GB1212的字元包含了ASCII字元,UTF8包含了GB2312字元。由此可見,UTF8是所含最廣字元的字元集,所以,在一些多語言的WEB系統中,一般用UTF8字元集(PHPMyAdmin使用UTF8編碼)。
任何文本的儲存,都滲及到字元集的概念。包括資料庫,也包括普通的文字檔。
編碼和字元集兩個概念極易混淆,因為一般情況下,編碼的名字和字元集的名字相同,如:GB2312既是一種字元集的名字,也是一種編碼格式的名字。
字元:漢字,英文字母,標點符號,拉丁文等等。
編碼:將字元轉換成電腦儲存的格式,比如,A用65表示。
字元集:一組字元以及對應的編碼方式。
可見字元集和編碼是兩個不同的概念。一個字元集可以有多種編碼方式,如Unicode字元集就有UTF-8、UTF-16、UTF-32等編碼方式。 charset=utf-8,在網頁中的意思是該頁面時採用Unicode字元集,並採用UTF-8編碼方式。
1.3 Mysql的字元集
Mysql目前支援多字元集,並且,支援在不同的字元集之間轉換(便於移植和支援多語言)。
Mysql可以設定伺服器級字元集、資料庫級字元集、資料表級字元集、表列的字元集,實際上,最終使用字元集的地方是儲存字元的列,比如,你設定 table1中col1列是字元類型,col1才用到了字元集,如果table1表的col2列是int類型,col2不使用字元集的概念。
伺服器級字元集、資料庫級字元集、資料表級字元集都是為列的字元集做預設選項的。
Mysql 一定有一個字元集,可以通過啟動時加參數指定,也可以編譯時間指定,也可以在設定檔裡指定。Mysql伺服器字元集,只是做為資料庫級的預設值。建立資料庫時,你可以指定字元集,如果沒指定,就使用伺服器的字元集。同理,建立表時,你可以指定表級的字元集,如果沒指定,使用資料庫的字元集做為表的字元集。建立列時,你可以指定某列的字元集,如果沒指定,就使用表的字元集。
通常情況下,您只需設定伺服器級的字元集,其它的資料庫級,表級,以及列級的字元集,都繼承自伺服器級字元集。
由於UTF8是最廣的字元集,所以,一般情況下,我們設定Mysql伺服器級的字元集為UTF8。
MYSQL中字元集的繼承關係
伺服器字元集(在設定檔中設定字元集的方式:my.ini [mysqld] default-character-set=utf8)
|
|
|
資料庫級字元集(如果建立資料庫是指定了字元集,則使用指定的字元集。如果沒有,則使用伺服器級的字元集)
|
|
|
表級字元集(建立表時指定了字元集,則使用指定的字元集。如果沒有,則使用資料庫級的字元集)
|
|
|
列級字元集(建立表時指定了列的字元集,則使用指定的字元集。如果沒有,則使用表級的字元集)
可見最終使用字元集的地方是儲存文本的列。
2 普通文本的字元集問題
任何文本的儲存,都存在著字元集的問題,普通文字檔也不例外。
Windows2000+的系統中,開啟記事本,"儲存為..."對話方塊,就有一個選項,可以讓你選擇儲存文本的編碼方式。
通常情況下,大家都使用Windows2000+的系統,都使用預設的編碼,所以,不會碰到字元集的問題。
Windows下,儲存文字檔時,可以選擇編碼方式,但開啟文字檔時,都是自動判斷編碼方式的。網上有一個用Windows2000+的記事本玩移動,聯通的笑話,大家可以搜搜,就是因為Windows在開啟文字檔時,編碼判斷錯誤引起的問題。
因為自動判斷編碼有時會錯誤,所以,有的文字檔,規定了如何識別自身所使用的編碼。HTML檔案就是一個這樣的例子。
HTML是文字檔。儲存HTML檔案的時候,需要使用一個編碼,並且,在HTML檔案裡,也使用HTML文法,指定了該檔案所使用的編碼(比如)。如果HTML檔案沒有指定編碼,則瀏覽器自動識別檔案的編碼。如果HTML指定了編碼,則瀏覽器使用HTML指定的編碼。
通常情況下,HTML檔案指定的charset和HTML檔案自身的編碼是一致的,但也有不一致的情況,如果不一致,就會導致網頁亂碼(此處亂碼,只和文字檔有關,和資料庫無關。)使用專門的網頁編輯工具(比如Dreamwave),會自動根據網頁中的charset值來編碼檔案。
例如:test.html
內容如下:
<h1>123地方活動家恢複搭街坊456</h1>
不管上述檔案儲存時使用什麼編碼方式,用瀏覽器開啟都會正常,不會出現亂碼。這是因為瀏覽器能自動識別編碼格式。
將上述檔案內容該為:
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<h1>123地方活動家恢複搭街坊456</h1>
這時test.html不使用UTF-8編碼格式儲存,瀏覽器開啟一定會出現亂碼。因為瀏覽器將使用UTF-8編碼來解析收到的資料。
3 php+mysql的字元集問題
PHP最終產生的是文字檔,但他要取資料庫裡的文本,或將文本存進資料庫。
由於Mysql支援多字元集,預設情況下,Mysql不知道PHP發給他的是什麼編碼的字元,所以,Mysql要求用戶端(PHP)告訴他存取的字元集是什麼。
PHP通過設定character_set_client,告訴Mysql,PHP存進資料庫的是什麼編碼方式。
PHP通過設定character_set_results,告訴Mysql,PHP需要取什麼樣編碼的資料。
PHP通過設定character_set_connection,告訴Mysql,PHP查詢中的文本,使用什麼編碼。
MYSQL使用設定的編碼方式儲存文本。
假設Mysql使用setserver來儲存文本,PHP的character_set_client是setclient,PHP的 character_set_results是setresult。那麼,Mysql將PHP發來的文本,從setclient編碼方式,轉換成 setserver編碼方式,再存入資料庫,如果PHP取文本,Mysql將文本從setserver轉換成setresult,再發送給PHP。
PHP檔案(最終產生的HTML檔案)本身有個編碼,如果Mysql傳過來的編碼,與PHP檔案自身的編碼不同,那麼,整個網頁,必然亂碼。所以,PHP一般將自己的編碼方式,告訴Mysql。
要保證不亂碼,就必須將三個編碼統一:一是網頁自身的編碼,二是HTML裡指定的編碼,三是PHP告訴Mysql的編碼(包括character_set_client和character_set_results)。
第一和第二個編碼,如果使用DW之類的編輯器寫的網頁,通常是一致的,但用記事本寫的網頁,有可能不一致。
第三個編碼,需要手工通知Mysql。這步可以通過在PHP裡使用mysql_query("set names characterX")來實現。
關於一些 MYSQL中的字元集概念