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/ 本文版权归做者和博客园共有,欢迎转载,但未经做者赞成必须保留此段声明,且在文章页面明显位置给出原文链接,不然保留追究法律责任的权利。