2007年10月28日 星期日

MySQL亂碼2

上一次碰到MySQL亂碼的問題,我順利解決了,而這次我遇到了與前一篇相似但是更棘手的問題,那就是MySQL直接升級後亂碼一大堆的中文資料庫!

事情是這樣的,我從MySQL 4.0.XX版本直接升級到5.0.XX,在升級的過程中沒有使用mysqldump備份資料庫出來,所以升級後原本儲存中文的資料庫全成了亂碼!這下糟糕了,與前依次遇到的情形不同,上一次我還能用mysqldump把變成亂碼的資料庫輸出後以utf8格式觀看,並檢查正確性,這次可沒辦法這麼做了,因為我用5.0.XX版本的mysqldump輸出不管怎麼看都是亂碼,因為mysqldump 4.0與5.0對資料庫編碼的作法不一樣,輸出結果也不一樣!

怎麼辦呢?我只好從都開始研究4.0到底怎麼把各式各樣的編碼儲存在資料庫裡。

MySQL 4.0使用的是latin1字集,不管外部使用的是甚麼字集,在存入MySQL資料庫時一律以latin1的方式儲存,所以即使是utf8字集,在回存MySQL時還是以latin1的方法分辨並拆解utf8的字集,而提取資料時,MySQL就反過來執行拆解程式,將那陀亂七八糟的latin1字符反過來轉換,變成utf8字符,而這樣做居然不會有事。

經過這樣的研究,我們知道MySQL早期處理i18n的方法相當粗糙,但也提示我們MySQL早期的儲存媒介實際上是以0/1的二元概念在儲存文字資料,才能讓latin1儲存utf8這種奇妙的事情發生。在懂了這個過程後,我試出來如何將latin1字集儲存的utf8正常倒出來了--利用mysqldump配上選項強制指定輸出字集。例如:

mysqldump --default-character-set=latin1 DB_NAME > backup.txt

利用firefox或類似的瀏覽器觀看這份文件,就可以發現他能顯示uft8或big5的字元了!但是,你若是將此文件直接輸入新版MySQL,卻發現他依然還是亂碼!

為什麼呢?因為問題出在文件的內容!

請找一下文件開頭幾行,應該會看見這一行:
/*!40101 SET NAMES latin1 */;
這句話指定了MySQL在輸入此文件時以latin1解碼,所以你的utf8或big5文件就會被強迫以latin1儲存,這樣在新版MySQL環境中就會真的變亂碼了!

怎麼辦呢?改文件內容就好!依照你想要的字集,例如我要轉換的文件是以utf8為準,我就將他改成
/*!40101 SET NAMES utf8 */;

順便尋找一下文件裡面關於CREATE TABLE的敘述中有沒有
DEFAULT CHARSET=latin1;
之類的文字,請將其中的latin1改成utf8或big5,當你將整份文件的CREATE TABLE都改完後,這份SQL指令檔就會以utf8或big5處理你的文字資料了,這樣應該就能解決跨版本MySQL轉移的亂碼問題了。

請好好享受。

沒有留言: