浅谈MySQL备份字符集的问题

1 引子

MySQL备份时选择字符集是一个难题,特别是字符集不定的业务。mysqldump默认使用utf8,而官方也推荐使用utf8。但实际上,对于中文,部分至关一部分gbk编码字符没有对应的unicode编码,也就是说这部分字符集使用utf8备份会致使数据丢失。那么有没有解决方法呢?mysql

固然,最直接的方法是将这部分编码的映射加上。可是,这部分的字符集数量并非少数,并且,更蛋疼的是,彷佛找不到这部分字符集权威的映射标准。那么,还有其它方法吗?sql

实际上,若是使用binary进行备份,就不会存在字符集的转换过程,也就不会存在上述问题。那么,使用binary是否就解决了gbk全部的问题呢?答案是NO。编码

2 binary的问题

在讲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');

clip_image002

能够看到,正常导出的表,导入却出现1067 Invalid default value的错误。

3 解决方法

mysqldump时,在执行create table语句以前,增长对character_set_connection 的设置。

/*!40101 SET character_set_connection = utf8 */

clip_image004

clip_image006

这也算是MySQL一个bug,既然schema信息从头至尾都使用utf8,在执行create table以前,就应该将链接的字符集变量设置成utf8,而不是只设置client的字符集变量。

 


做者:YY哥
出处:http://www.cnblogs.com/hustcat/ 本文版权归做者和博客园共有,欢迎转载,但未经做者赞成必须保留此段声明,且在文章页面明显位置给出原文链接,不然保留追究法律责任的权利。

相关文章
相关标签/搜索