posts - 495,  comments - 11,  trackbacks - 0
          最近discuz發(fā)布了新的版本,免費(fèi)了,用的人更多了,以前使用其它論壇程序和discuz2.5/3.0的紛紛轉(zhuǎn)換或升級(jí)到discuz4.0,可見discuz作為中國(guó)人開發(fā)的php論壇程序,確實(shí)是非常優(yōu)秀的,在大家欣喜若狂的時(shí)候,也遇到了一些問題
            
            看到不少用戶反映轉(zhuǎn)換完以后是亂碼的情況,出現(xiàn)這種現(xiàn)象的主要原因是這類用戶使用的都是mysql4.1以上的版本.下面作一個(gè)說明,希望出現(xiàn)這個(gè)問題的朋友都能耐心的把這個(gè)文檔看完!!!
            
            MySQL 4.1開始,對(duì)多語言的支持有了很大變化 (這導(dǎo)致了問題的出現(xiàn))。盡管大部分的地方 (包括個(gè)人使用和主機(jī)提供商),MySQL 3、4.0 仍然占主導(dǎo)地位;但 MySQL 4.1 乃至5.0是 MySQL 官方推薦的數(shù)據(jù)庫(kù),已經(jīng)有主機(jī)提供商開始提供并將會(huì)越來越多;因?yàn)?latin1 在許多地方 (下邊會(huì)詳細(xì)描述具體是哪些地方) 作為默認(rèn)的字符集,成功的蒙蔽了許多 PHP 程序的開發(fā)者和用戶,掩蓋了在中文等語言環(huán)境下會(huì)出現(xiàn)的問題。
            
            MySQL 4.1開始把多國(guó)語言字符集分的更加詳細(xì),所以導(dǎo)致數(shù)據(jù)庫(kù)遷移,或則dz論壇升級(jí)到4.0后(dz4.0開始使用gbk或utf-8編碼)出現(xiàn)亂碼問題。
            
            MySQL 4.1的字符集支持(Character Set Support)有兩個(gè)方面:字符集(Character set)和排序方式(Collation)。對(duì)于字符集的支持細(xì)化到四個(gè)層次: 服務(wù)器(server),數(shù)據(jù)庫(kù)(database),數(shù)據(jù)表(table)和連接(connection)。
            
            查看系統(tǒng)的字符集和排序方式的設(shè)定可以通過下面的兩條命令:
            
          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 對(duì)于字符集的指定可以細(xì)化到一臺(tái)機(jī)器上安裝的 MySQL,其中的一個(gè)數(shù)據(jù)庫(kù),其中的一張表,其中的一欄,應(yīng)該用什么字符集。但是,傳統(tǒng)的 Web 程序在創(chuàng)建數(shù)據(jù)庫(kù)和數(shù)據(jù)表時(shí)并沒有使用那么復(fù)雜的配置,它們用的是默認(rèn)的配置,那么,默認(rèn)的配置從何而來呢?
            
            編譯 MySQL 時(shí),指定了一個(gè)默認(rèn)的字符集,這個(gè)字符集是 latin1;
            安裝 MySQL 時(shí),可以在配置文件 (my.ini) 中指定一個(gè)默認(rèn)的的字符集,如果沒指定,這個(gè)值繼承自編譯時(shí)指定的;
            啟動(dòng) mysqld 時(shí),可以在命令行參數(shù)中指定一個(gè)默認(rèn)的的字符集,如果沒指定,這個(gè)值繼承自配置文件中的;
            此時(shí) character_set_server 被設(shè)定為這個(gè)默認(rèn)的字符集;
            當(dāng)創(chuàng)建一個(gè)新的數(shù)據(jù)庫(kù)時(shí),除非明確指定,這個(gè)數(shù)據(jù)庫(kù)的字符集被缺省設(shè)定為 character_set_server;
            當(dāng)選定了一個(gè)數(shù)據(jù)庫(kù)時(shí),character_set_database 被設(shè)定為這個(gè)數(shù)據(jù)庫(kù)默認(rèn)的字符集;
            在這個(gè)數(shù)據(jù)庫(kù)里創(chuàng)建一張表時(shí),表默認(rèn)的字符集被設(shè)定為 character_set_database,也就是這個(gè)數(shù)據(jù)庫(kù)默認(rèn)的字符集;
            當(dāng)在表內(nèi)設(shè)置一欄時(shí),除非明確指定,否則此欄缺省的字符集就是表默認(rèn)的字符集;
            這個(gè)字符集就是數(shù)據(jù)庫(kù)中實(shí)際存儲(chǔ)數(shù)據(jù)采用的字符集,mysqldump 出來的內(nèi)容就是這個(gè)字符集下的;
            當(dāng)我們按照原來的方式通過PHP存取MySQL數(shù)據(jù)庫(kù)時(shí),就算設(shè)置了表的默認(rèn)字符集為utf8并且通過UTF-8編碼發(fā)送查詢,你會(huì)發(fā)現(xiàn)存入數(shù)據(jù)庫(kù)的仍然是亂碼。問題就出在這個(gè)connection連接層上。
            想要進(jìn)行“正確”的存儲(chǔ)和得到“正確”的結(jié)果,最方便的是在所有query開始之前執(zhí)行一下:
            
            SET NAMES 'gbk';
            其中g(shù)bk是數(shù)據(jù)庫(kù)字符集。
            
            它相當(dāng)于下面的三句指令:
            SET character_set_client = gbk;
            SET character_set_results = gbk;
            SET character_set_connection = gbk;
            
            4.1和5.0默認(rèn)使用的是latin1字符集(木頭:媽的,老外真霸道,妄想讓全世界都是使用瑞典字符集嗎)
            如果我們只想使用gbk字符集存儲(chǔ)和獲取數(shù)據(jù),
            我們?cè)诰幾gmysql 4.1和 5.0的時(shí)候,需要注意在my.ini或者my.cnf中添加兩處參數(shù)
            
          CODE:
          [mysqld]
            default-character-set=utf8

            
            
          CODE:
          #settings for clients (connection, results, clients)
            [mysql]
            default-character-set=utf8

            下面我們來說主題,如何轉(zhuǎn)換數(shù)據(jù)庫(kù)字符集
            兩種方法,
            
          QUOTE:
          第一種----更改存儲(chǔ)字符集
            主要的思想就是把數(shù)據(jù)庫(kù)的字符集有l(wèi)atin1改為gbk,big5,或者utf8; 以下操作必須擁有主機(jī)權(quán)限。假設(shè)當(dāng)前操作的數(shù)據(jù)庫(kù)名為:database
            
            導(dǎo)出
            首先需要把數(shù)據(jù)導(dǎo)為mysql4.0的格式,具體的命令如下:
            mysqldump -uroot -p --default-character-set=latin1 --set-charset=gbk --skip-opt databse > d4.sql
            
            mysqldump的參數(shù)參照:
            MySql數(shù)據(jù)庫(kù)備份mysqldump參數(shù)選項(xiàng)
            

            
            --default-characte-set 以前數(shù)據(jù)庫(kù)的字符集,這個(gè)一般情況下都是latin1的,
            --set-charset 導(dǎo)出的數(shù)據(jù)的字符集,這個(gè)可以設(shè)置為gbk,utf8,或者big5
            導(dǎo)入
            首先使用下面語句新建一個(gè)GBK字符集的數(shù)據(jù)庫(kù)(test)
            
            CREATE DATABASE `d4` DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci;
            然后把剛才導(dǎo)出的數(shù)據(jù)導(dǎo)入到當(dāng)前的數(shù)據(jù)庫(kù)中就ok了。
            
            mysql -uroot -p --default-character-set=gbk -f d4 通過以上的導(dǎo)出和導(dǎo)入就把數(shù)據(jù)庫(kù)的字符集改為正確的存儲(chǔ)方式了。
            
            其中d4為新建庫(kù)的名稱,d4.sql為導(dǎo)出文件的名字
            
            但是這種方法,發(fā)現(xiàn)數(shù)據(jù)庫(kù)數(shù)據(jù)存儲(chǔ)量無端變大30%,真是郁悶

            
            
          QUOTE:
          另外一種其實(shí)原理相同,但是需要手動(dòng)操作,一般用于第一種方法失敗后的選擇
            不過這種方法如果數(shù)據(jù)庫(kù)很大,估計(jì)很難做,因?yàn)楣獯蜷_文件就能讓你死機(jī)
            
            首先還是用phpmyadmin或者用mysql本身的dump導(dǎo)出 .sql文件
            
            然后用UltraEdit打開你備份的所有xxxx.sql文件,查找
            
          CODE:
          DEFAULT CHARSET=latin1

            latin1這里也許是別的,反正是你不想要的,要轉(zhuǎn)成gbk或者big5的字符集
            把這個(gè)替換為“空”
            在查找
            
          CODE:
          CREATE TABLE cdb_sessions (
            sid char(6) character set latin1 collate latin1_bin NOT NULL default '',
            ip1 tinyint(3) unsigned NOT NULL default '0',
            ip2 tinyint(3) unsigned NOT NULL default '0',
            ip3 tinyint(3) unsigned NOT NULL default '0',
            ip4 tinyint(3) unsigned NOT NULL default '0',
            uid mediumint(8) unsigned NOT NULL default '0',
            username char(15) NOT NULL default '',
            groupid smallint(6) unsigned NOT NULL default '0',
            styleid smallint(6) unsigned NOT NULL default '0',
            invisible tinyint(1) NOT NULL default '0',
            `action` tinyint(1) unsigned NOT NULL default '0',
            lastactivity int(10) unsigned NOT NULL default '0',
            fid smallint(6) unsigned NOT NULL default '0',
            tid mediumint(8) unsigned NOT NULL default '0',
            nickname char(15) NOT NULL default '',
            UNIQUE KEY sid (sid)
            ) ENGINE=HEAP MAX_ROWS=1000;

            替換為
            
          CODE:
          CREATE TABLE `cdb_sessions` (
            `sid` char(6) binary NOT NULL default '',
            `ip1` tinyint(3) unsigned NOT NULL default '0',
            `ip2` tinyint(3) unsigned NOT NULL default '0',
            `ip3` tinyint(3) unsigned NOT NULL default '0',
            `ip4` tinyint(3) unsigned NOT NULL default '0',
            `uid` mediumint(8) unsigned NOT NULL default '0',
            `username` char(15) NOT NULL default '',
            `groupid` smallint(6) unsigned NOT NULL default '0',
            `styleid` smallint(6) unsigned NOT NULL default '0',
            `invisible` tinyint(1) NOT NULL default '0',
            `action` tinyint(1) unsigned NOT NULL default '0',
            `lastactivity` int(10) unsigned NOT NULL default '0',
            `fid` smallint(6) unsigned NOT NULL default '0',
            `tid` mediumint(8) unsigned NOT NULL default '0',
            `nickname` char(15) NOT NULL default '',
            UNIQUE KEY `sid` (`sid`)
            ) TYPE=HEAP MAX_ROWS=2000;

            這一步更為簡(jiǎn)單的辦法就是刪除掉關(guān)于cdb_sessions表的這一段,將來全新裝一個(gè)d4,將這個(gè)表導(dǎo)出
            將其內(nèi)容復(fù)制,粘貼到 sql文件的最后面
            
            保存后,再把這個(gè)sql文件導(dǎo)入到你的庫(kù)中
            
            就OK了

            用這兩種方法就可以很方便的把4.1和5.0的mysql數(shù)據(jù)庫(kù)降級(jí)到4.0
            簡(jiǎn)單的過程就是
            A導(dǎo)出4.1/5.0的庫(kù)
            B進(jìn)行處理,轉(zhuǎn)換成gbk字符集
            C徹底卸載4.1或者5.0
            D安裝4.0.26
            E然后導(dǎo)入處理完的庫(kù)
            
            降級(jí)的時(shí)候?qū)С鰩?kù)可以用這個(gè)方法
            mysqldump -uroot -p --default-character-set=latin1 --set-charset=gbk --skip-opt databse --compatible=mysql40 > d4.sql
            這樣導(dǎo)出的就是4.0的庫(kù)勒
            
            至于mysql版本的升級(jí),
            如果數(shù)據(jù)文件中有中文信息,那么將MySQL 4.0的數(shù)據(jù)文件,直接拷貝到MySQL 4.1中就是不可以的,即便在my.ini中設(shè)置了default-character-set為正確的字符集。雖然貌似沒有問題,但MySQL 4.1的字符集有一處非常惱人的地方,以gbk為例,原本MySQL 4.0數(shù)據(jù)中varchar,char等長(zhǎng)度都會(huì)變?yōu)樵瓉淼囊话耄@樣存儲(chǔ)中文容量不變,而英文的存儲(chǔ)容量就少了一半。這是直接拷貝數(shù)據(jù)文件帶來的最大問題。
            
            所以,升級(jí)的根本,如果想使用“正確”的字符集,還是先用mysqldump導(dǎo)出成文件,然后導(dǎo)入。
            
            
            這里順便提一個(gè)我的好友深海寫的
            用于MySQL4.1的論壇數(shù)據(jù)庫(kù)字符集整理工具。
            
            剛寫的,處理部分代碼可能寫得有點(diǎn)齷齪,但是不影響使用,
            
            
            主要用于處理整理MySQL4.1指定數(shù)據(jù)庫(kù)、表、字段的字符集。
            
            適用于將非允許的字符集范圍內(nèi)的數(shù)據(jù)結(jié)構(gòu)(無數(shù)據(jù)!!)整理為適合Discuz!允許的字符集范圍。
          posted on 2007-12-16 22:50 jadmin 閱讀(54) 評(píng)論(0)  編輯  收藏

          只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           
          主站蜘蛛池模板: 六枝特区| 泰和县| 保康县| 德阳市| 迁西县| 修武县| 通道| 富民县| 长丰县| 汉川市| 乌恰县| 武城县| 石屏县| 福清市| 江西省| 靖边县| 芮城县| 克什克腾旗| 鄯善县| 广南县| 浦北县| 恩平市| 浠水县| 安溪县| 缙云县| 界首市| 阿拉善左旗| 宜章县| 敖汉旗| 顺义区| 夏河县| 梁山县| 浦北县| 柏乡县| 陇川县| 黎川县| 叶城县| 介休市| 惠来县| 台湾省| 吉水县|