最近discuz發布了新的版本,免費了,用的人更多了,以前使用其它論壇程式和discuz2.5/3.0的紛紛轉換或升級到discuz4.0,可見discuz作為中國人開發的php論壇程式,確實是非常優秀的,在大家欣喜若狂的時候,也遇到了一些問題
看到不少使用者反映轉換完以後是亂碼的情況,出現這種現象的主要原因是這類使用者使用的都是mysql4.1以上的版本.下面作一個說明,希望出現這個問題的朋友都能耐心的把這個文檔看完!!!
MySQL 4.1開始,對多語言的支援有了很大變化 (這導致了問題的出現)。儘管大部分的地方 (包括個人使用和主機供應商),MySQL 3、4.0 仍然佔主導地位;但 MySQL 4.1 乃至5.0是 MySQL 官方推薦的資料庫,已經有主機供應商開始提供並將會越來越多;因為 latin1 在許多地方 (下邊會詳細描述具體是哪些地方) 作為預設的字元集,成功的蒙蔽了許多 PHP 程式的開發人員和使用者,掩蓋了在中文等語言環境下會出現的問題。
MySQL 4.1開始把多國語言字元集分的更加詳細,所以導致資料庫遷移,或則dz論壇升級到4.0後(dz4.0開始使用gbk或utf-8編碼)出現亂碼問題。
MySQL 4.1的字元集支援(Character Set Support)有兩個方面:字元集(Character set)和排序方式(Collation)。對於字元集的支援細化到四個層次: 伺服器(server),資料庫(database),資料表(table)和串連(connection)。
查看系統的字元集和排序方式的設定可以通過下面的兩條命令:
QUOTE:
mysql> SHOW VARIABLES LIKE 'character_set_%';
+--------------------------+----------------------------+
| Variable_name | Value |
+--------------------------+----------------------------+
| character_set_client | latin1 |
| character_set_connection | latin1 |
| character_set_database | latin1 |
| character_set_results | latin1 |
| character_set_server | latin1 |
| character_set_system | utf8 |
| character_sets_dir | /usr/share/mysql/charsets/ |
+--------------------------+----------------------------+
7 rows in set (0.00 sec)
mysql> SHOW VARIABLES LIKE 'collation_%';
+----------------------+-------------------+
| Variable_name | Value |
+----------------------+-------------------+
| collation_connection | latin1_swedish_ci |
| collation_database | latin1_swedish_ci |
| collation_server | latin1_swedish_ci |
+----------------------+-------------------+
3 rows in set (0.00 sec)
MySQL 4.1 對於字元集的指定可以細化到一台機器上安裝的 MySQL,其中的一個資料庫,其中的一張表,其中的一欄,應該用什麼字元集。但是,傳統的 Web 程式在建立資料庫和資料表時並沒有使用那麼複雜的配置,它們用的是預設的配置,那麼,預設的配置從何而來呢?
編譯 MySQL 時,指定了一個預設的字元集,這個字元集是 latin1;
安裝 MySQL 時,可以在設定檔 (my.ini) 中指定一個預設的的字元集,如果沒指定,這個值繼承自編譯時間指定的;
啟動 mysqld 時,可以在命令列參數中指定一個預設的的字元集,如果沒指定,這個值繼承自設定檔中的;
此時 character_set_server 被設定為這個預設的字元集;
當建立一個新的資料庫時,除非明確指定,這個資料庫的字元集被預設設定為 character_set_server;
當選定了一個資料庫時,character_set_database 被設定為這個資料庫預設的字元集;
在這個資料庫裡建立一張表時,表預設的字元集被設定為 character_set_database,也就是這個資料庫預設的字元集;
當在表內設定一欄時,除非明確指定,否則此欄預設的字元集就是表預設的字元集;
這個字元集就是資料庫中實際儲存資料採用的字元集,mysqldump 出來的內容就是這個字元集下的;
當我們按照原來的方式通過PHP存取MySQL資料庫時,就算設定了表的預設字元集為utf8並且通過UTF-8編碼發送查詢,你會發現存入資料庫的仍然是亂碼。問題就出在這個connection串連層上。
想要進行“正確”的儲存和得到“正確”的結果,最方便的是在所有query開始之前執行一下:
SET NAMES 'gbk';
其中gbk是資料庫字元集。
它相當於下面的三句指令:
SET character_set_client = gbk;
SET character_set_results = gbk;
SET character_set_connection = gbk;