如何解决Mysql中中文乱码的问题
在实践过程中遇到了MySQL存储中文乱码的问题,翻阅相关书籍并进行网上查询后,对此问题有了一定的了解,记录下来希望能够对别人有所帮助。
一.字符集与字符序
mysql出现中文乱码的原因是字符集的转换过程出了问题,首先介绍一下字符集与字符序。
字符集 就是字符与某一编码的对应关系组成的集合。
例如,在ascii中 65(编码)对应 A(字符),很多这种对应组合起来构成了ascii字符集。
正是由于不同的字符以及它们所对应的编码的不同产生了不同的字符集。例如gbk常常用来表示汉字(字符),而ascii中根本没有汉字字符,这就是字符集中字符范围的不同;而gbk和utf8可能都具有某一汉字,但是这一个汉字在这两套字符集中对应的编码却不相同,这是编码的差异。因此,在mysql中字符集的转换过程中,如果发生了字符集不对应的情况,比如我用A字符集编码,你却用B字符集解码,自然得不到正确的字符,也就发生了乱码。
字符序 是指在同一字符集中的字符间的比较规则。
这就好比字符是我们数学上的自然数,但是只告诉了你1,2,3你并不知道哪个更大,因为我们还没一定义比较的规则。在我们生活常识中1<2<3,这便是一个字符集的默认字符序。也许在另一个宇宙中是1>2>3,也就是说还有默认字符序之外的其它字符序。
例如对于latin1字符集,有latin1_danish_ci,latin1_swedish_ci,latin_bin等字符序。
字符序的命名也是有规则的:以字符集的名称开头,以国家名或者general居中,以ci,cs,bin结尾。其中ci代表大小写不敏感,cs代表大小写敏感,bin表示按二进制编码值比较。
二.检查自己的mysql字符集配置
下面就要以代码说话了。
在mysql中:
show character set; #展示当前支持的字符集
show collation; #展示当前支持的字符序
show variables like 'character%'; #展示当前mysql的字符集配置
show variables like 'collation%'; #展示当前的字符序配置
比如:
这是我设置完成后的,在默认情况下并非如此。如果你发生了乱码的情况,并且发现自己的某些字符集(下面介绍)配置并不统一,那么乱码产生的原因极有可能发生在这里。
首先说一下各个variable_name的含义:
- character_set_client:mysql的客户端的字符集,默认安装后value为latin1。
- character_set_connection:数据通信链路的字符集,当mysql客户端向服务器发送请求时以该字符集编码。默认安装后为latin1。
- character_set_database:数据库字符集,默认安装后为latin1。
- character_set_filesystem:mysql服务器文件系统的字符集,该值是固定的binary。
- character_set_results:结果集的字符集,mysql服务器向客户端返回执行结果时执行结果以该字符集进行编码。默认安装后值为latin1。
- character_set_server:服务器的字符集,默认为latin1。
- character_set_system:元数据(字段名,表名,数据库名等)的字符集,默认为utf8。
要解决乱码问题最重要的是
- character_set_client,character_set_connection, character_set_results
- character_set_server
之所以这样分类是有原因的。
首先,character_set_client,character_set_connection, character_set_results这三个往往是一同进行设置的; 其次,在没有明确指明字符集的情况下,字段名沿用表名,表名沿用数据库(character_set_database),数据库沿用character_set_server。因此,只要设置了character_set_server,也就统一了character_set_database。
三.乱码的解决—设置字符集
设置字符集有多种方法,主要分为临时的和永久的。临时的就是输入命令,永久的是修改文件。
修改文件
在linux(ubuntu 17.01)下的/etc/mysql/的目录中有my.cnf文件,可以进行如下修改:
将[mysql]选项组中的default-character-set参数值进行修改可以改变character_set_client,character_set_connection, character_set_results。
将[mysqld]选项组中的character-set-server进行修改可以改变character-set-server。
例如:
[mysql]
default-character-set=utf8
[mysqld]
character-set-server=utf8
或者设置为gbk(图中倒数的四行)
注意:
- 注意[mysql]与[mysqld]
- character-set-server 与character_set_server写法等价(至少我测试的如此)
- windows中该文件好像叫做my.ini,可自行搜索。
临时修改
通过命令也可以进行修改(所谓临时修改即只有本次与服务器的链接有效)
set names gbk;
/*修改character_set_client,character_set_connection, character_set_results*/
数据库和表可以在创建时指定(否则将向上继承,前面以提到)。
要重点注意的是,无论是修改文件还是临时命令,都只影响新数据。
还有一个最最重要的问题,千万别忘记修改文件后重新启动mysql,不是退出再进入,是重新启动服务。
/etc/init.d/mysql restart
(ubuntu 17.01)
推荐阅读