故障回顾
- 时间 2012-08-30 09:00 - 10:00
- ugc3 数据库迁移
- 迁移方法,mysqldump备份,然后在source导入.
- 手动source导入的数据没有问题,可以正常显示.
- 用程序连接,输入的新数据则无法正常显示,出现乱码.
- 发现数据库问题后,执行回滚.
测试/分析
- l-db1.wap.cn1的情况
MySQL是Percona的二进制版本.默认字符集是Latin1
库和表的字符集是utf8(utf8mb4)
配置文件中指定了如下选项character_set_server = utf8 collation_server = utf8_general_ci
- 查看当前会话的char%状态,没有问题
- 无奈之下,重启了3309端口的MySQL实例,重启之后,问题清除.
- 为了排除导入数据需要重启MySQL的假设,又重新导入了一遍ugc3数据,程序测试正常,没有发现乱码.
- 在l-db2.f.cn1的3309实例中,查看全局的char%状态时,发现问题
show global variables like 'char%'; +--------------------------+-------------------------------+ | Variable_name | Value | +--------------------------+-------------------------------+ | character_set_client | latin1 | | character_set_connection | latin1 | | character_set_database | utf8 | | character_set_filesystem | binary | | character_set_results | latin1 | | character_set_server | utf8 | | character_set_system | utf8 | | character_sets_dir | /home/q/mysql/share/charsets/ | +--------------------------+-------------------------------+
- 回忆: 最初安装的时候,没有在配置文件中指定utf8字符集
- 后来发现问题,执行过如下sql
set global character_set_database = utf8; set global character_set_server = utf8;
- 但是修改的不彻底,与客户端进行交互的三个选项没有更改,导致这次问题.
- 彻底修改,应该执行如下sql
set global character_set_client = utf8; set global character_set_connection = utf8; set global character_set_database = utf8; set global character_set_results = utf8; set global character_set_server = utf8;
- 注意:该变量不会在MySQL的配置比较中显示出来.
MySQL如何使用字符集
- 当创建一个数据库的时候,它从服务器继承了character_set_server设置
- 当创建表的时候,它从数据库继承字符集
- 当创建列的时候,它从表继承字符集
MySQL用于client/server沟通的设置(翻译过程)
- 服务器假设客户端正在按照character_set_client设置的字符集发送数据.
- 服务器从客户端接收到语句后, 它按照character_set_connection设置的字符集地数据进行翻译, 它也会用这个字符集决定如何把数字转换为字符串.
- 当服务器把结果或错误信息返回给客户端时,它会按照character_set_result定义的字符集进行翻译.