MySQL備份時選擇字符集是一個難題,特別是字符集不定的業務。mysqldump默認使用utf8,而官方也推薦使用utf8。但實際上,對於中文,部分至關一部分gbk編碼字符沒有對應的unicode編碼,也就是說這部分字符集使用utf8備份會致使數據丟失。那麼有沒有解決方法呢?mysql
固然,最直接的方法是將這部分編碼的映射加上。可是,這部分的字符集數量並非少數,並且,更蛋疼的是,彷佛找不到這部分字符集權威的映射標準。那麼,還有其它方法嗎?sql
實際上,若是使用binary進行備份,就不會存在字符集的轉換過程,也就不會存在上述問題。那麼,使用binary是否就解決了gbk全部的問題呢?答案是NO。編碼
在講binary的問題以前。須要弄清2個問題。對於MySQL備份,分兩部分:schema信息和實際數據。而Schema信息一概使用utf8編碼,可是,default value除外。這正是問題的來源。url
2.1 utf8備份spa
(1)文件.frm會存儲table的schema信息,並經過一個實際的記錄來存儲各個field的默認值。Schema對應的信息(包括comment)使用utf8存儲,可是default value使用table指定的字符集進行存儲。code
(2)當執行show create table語句時,mysqld會將frm中的默認值從table指定的編碼轉成utf8編碼。blog
(3)當mysqld執行create table語句,會將default value從utf8轉成table指定的字符集。ip
2.2 binary備份ci
若是指定binary進行備份。在導入時,在建立table以前,雖然將character_set_client指定爲utf8,但collation_connection仍是binary。因此,存儲默認值時不會進行utf8到table指定的字符集的轉換。若是table指定爲gbk編碼,導入必然失敗。unicode
示例:
CREATE TABLE `t1`( `iNetbarId` int(11) NOT NULL DEFAULT '0', `iUin` bigint(20) NOT NULL DEFAULT '0', `vNetbarName` varchar(80) NOT NULL DEFAULT '「-」', PRIMARY KEY (`iNetbarId`) ) ENGINE=InnoDB DEFAULT CHARSET=gbk;
insert into t1 values(1,1,'xxxx'); |
能夠看到,正常導出的表,導入卻出現1067 Invalid default value的錯誤。
mysqldump時,在執行create table語句以前,增長對character_set_connection 的設置。
/*!40101 SET character_set_connection = utf8 */
這也算是MySQL一個bug,既然schema信息從頭至尾都使用utf8,在執行create table以前,就應該將鏈接的字符集變量設置成utf8,而不是隻設置client的字符集變量。
做者:YY哥
出處:http://www.cnblogs.com/hustcat/ 本文版權歸做者和博客園共有,歡迎轉載,但未經做者贊成必須保留此段聲明,且在文章頁面明顯位置給出原文鏈接,不然保留追究法律責任的權利。