今天碰到一个Case,是数据库导入的,很顺利地解决了,跟大家分享一下过程。
环境:
数据源服务器
mysql>show variables like ‘char%’;
character_set_client gbk
character_set_connection gbk
character_set_database gbk
character_set_results gbk
character_set_server gbk
character_set_system utf8
所有环境都是gbk,但备份脚本是这样的:
mysqldump my_db_name /home/leakon/db_bak/dump.sql
打开dump.sql,里面的中文字符都变成乱码了,在这个文件的头部,可以看到这么一行:
/*!40101 SET NAMES utf8 */;
也就是说,mysql在导出的时候,按照utf8字符集,进行了编码转换。
你可以这么理解,你和我都是中国人,说汉语,但我们之间沟通的时候用了一个翻译,这个翻译是英国人。
我就是那个数据源,英国的翻译就是dump.sql,我要跟你说中国话, 但翻译先把汉语翻译成英语,存在他的脑子里了。
这个时候你看他的内容,是没法理解的,这就是你看到的乱码。
下面,要把导出的数据,导入到新数据库中。
注意了,应该用下面的脚本:
mysql –default-character-set=latin1 -uroot my_new_db < dump.sql
我指定了latin1,作为连接mysql服务器的字符集。
实际上,导入的过程,就是让那个英国翻译,把英语再转换成汉语告诉你。这时,指定了latin1字符集, 就是告诉翻译,你让他把脑子里存的话,用英语翻译成汉语告诉你。
这里必须指定latin1,我也很奇怪为什么不指定utf8,我试过,不成功,服务器提示不支持这种编码。
具体原因我还会再研究,目前解决办法就是这样了。
指定字符集,就是让翻译按英语->汉语的转换程序进行翻译,否则,翻译可能是按英语->法语的顺序转换的,也就证明了,为什么导入数据库时,不指定编码,会是奇怪的乱码字符。
这里还有一个重要因素,就是数据库的字符集。
这个 my_new_db 创建的时候指定的是 gbk 字符集,建表语句是:
CREATE DATABASE my_new_db DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci;
如果数据库的字符集和源数据库不一样,那么,在导入时,很肯能出现导入到一半,MySQL报语法错,或者本来10万行数据只导入了2万行就停了。
原因就是编码转换时解析引擎会把其中的某些字符理解为引号等字符,导致语法错乱。
其实,有彻底解决这些编码问题的办法,那就是保证所有过程都指定正确的编码。
下面就以gbk为例:
- 源数据库,数据库、表和字符串字段的编码统一设定为gbk
- PHP调用程序时,在创建MySQL连接后立即发送一条 set names ‘gbk’ 语句
- 导出时指定gbk字符集:mysqldump -uroot –opt –default-character-set=gbk my_db_name > dump.sql
- 检查文件内容,应该是正确编码的字符,用普通文本编辑器可以阅读
- 目标数据库建库脚本:CREATE DATABASE my_new_db DEFAULT CHARACTER SET gbk COLLATE gbk_chinese_ci
- 导入时:mysql –default-character-set=gbk -uroot my_new_db < dump.sql
就这几个简单的步骤,就完全避免编码问题!
如果你要用utf8编码,把上述脚本的gbk都替换成utf8,把 gbk_chinese_ci 替换成 utf8_general_ci。
再重新导入,编码没问题,数据也完全导入了吧。