https://www.cnblogs.com/discuss/articles/1862248.html
http://www.cnblogs.com/zhoujinyi/p/4618887.html
背景:
update乱码
表和字段的字符集是正确的utf8
解决:
mysql> show variables like 'character%';
+--------------------------+----------------------------+| Variable_name | Value |+--------------------------+----------------------------+| character_set_client | utf8 || character_set_connection | utf8 || character_set_database | latin1 || character_set_filesystem | binary || character_set_results | utf8 || character_set_server | latin1 || character_set_system | utf8 || character_sets_dir | /usr/share/mysql/charsets/ |+--------------------------+----------------------------+8 rows in set (0.00 sec)名词解释:
– character_set_server:默认的内部操作字符集
– character_set_client:客户端来源数据使用的字符集– character_set_connection:连接层字符集– character_set_results:查询结果字符集– character_set_database:当前选中数据库的默认字符集– character_set_system:系统元数据(字段名等)字符集– 还有以collation_开头的同上面对应的变量,用来描述字符序。
1. MySQL Server收到请求时将请求数据从character_set_client转换为character_set_connection;
2. 进行内部操作前将请求数据从character_set_connection转换为内部操作字符集,其确定方法如下: - 使用每个数据字段的CHARACTER SET设定值; - 若上述值不存在,则使用对应数据表的DEFAULT CHARACTER SET设定值(MySQL扩展,非SQL标准); - 若上述值不存在,则使用对应数据库的DEFAULT CHARACTER SET设定值; - 若上述值不存在,则使用character_set_server设定值。3. 将操作结果从内部操作字符集转换为character_set_results。
修改默认字符集
(1) 最简单的修改方法,就是修改mysql的my.ini文件中的字符集键值, 如 default-character-set = utf8 mysql character_set_server = utf8 mysqld 修改完后,重启mysql的服务(2) 还有一种修改字符集的方法,就是使用mysql的命令 实践无用 mysql> SET character_set_client = utf8 ; mysql> SET character_set_connection = utf8 ; mysql> SET character_set_database = utf8 ; mysql> SET character_set_results = utf8 ; mysql> SET character_set_server = utf8 ; mysql> SET collation_connection = utf8 ; mysql> SET collation_database = utf8 ; mysql> SET collation_server = utf8 ;
然后就解决了,这里的矛盾在于,表和字段都设置了utf-8,却乱码了
总之,字段-表-库-服务器 都utf-8吧,不再深究
本文来自:
要了解为什么会出现乱码,我们就先要了解从客户端发起请求,到MySQL存储数据,再到下次从表取回客户端的过程中,哪些环节会有编码/解码的行为。为了更好的解释这个过程,博主制作了两张流程图,分别对应存入和取出两个阶段。
存入MySQL经历的编码转换过程
上图中有3次编码/解码的过程(红色箭头)。三个红色箭头分别对应:客户端编码,MySQL Server解码,Client编码向表编码的转换。其中Terminal可以是一个Bash,一个web页面又或者是一个APP。本文中我们假定Bash是我们的Terminal,即用户端的输入和展示界面。图中每一个框格对应的行为如下:- 在terminal中使用输入法输入
- terminal根据字符编码转换成二进制流
- 二进制流通过MySQL客户端传输到MySQL Server
- Server通过character-set-client解码
- 判断character-set-client和目标表的charset是否一致
- 如果不一致则进行一次从client-charset到table-charset的一次字符编码转换
- 将转换后的字符编码二进制流存入文件中
从MySQL表中取出数据经历的编码转换过程
上图有3次编码/解码的过程(红色箭头)。上图中三个红色箭头分别对应:客户端解码展示,MySQL Server根据character-set-client
编码,表编码向character-set-client
编码的转换。 -
- 从文件读出二进制数据流
- 用表字符集编码进行解码
- 将数据转换为character-set-client的编码
- 使用character-set-client编码为二进制流
- Server通过网络传输到远端client
- client通过bash配置的字符编码展示查询结果
https://www.linuxidc.com/Linux/2017-04/143263.htm
MySQL关于character有如下8个变量:
character_set_client
character_set_connection
character_set_database
character_set_filesystem
character_set_results
character_set_server
character_set_system
character_sets_dir
结论:
character_set_client、character_set_connection、character_set_results这3个参数值是由客户端每次连接进来设置的,和服务器端没关系。
我们登陆进mysql后,执行 set names utf8; 实际就是同时修改上面的这3个参数值的。
环境:
6.7x86_64
Percona Server 5.7 (server段设置的是character-set-server= utf8)
在Windows上使用CMD命令行去连接node1,如下图:
在Windows上使用SQLyog命令行去连接node1,如下图:
可以看到2个工具连接到同一个服务器上,显示出的参数却不一样的。
从官方文档中可以看出character_set_connection、character_set_client、character_set_results三个字符集什么时候用到。
从实际上可以看到,当客户端连接服务器的时候,它会将自己想要的字符集名称发给mysql服务器,然后服务器就会使用这个字符集去设置character_set_client、character_set_connection、character_set_results这三个值。如cmd是用gbk,而SQLyog是用utf8.
如果我们想告诉mysql server自己本次连接想使用latin1,则命令行下可以如下写法:
mysql -uroot -h 192.168.2.11 -pAbcd@1234 --default-character-set=latin1
此外,要修改上面的3个字符集的话,
还可以在my.cnf的[mysql]段里面增加:
default-character-set=latin1
也可以登录进去后,执行set names latin1的效果相同。