mysql字符集问题

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吧,不再深究

本文来自:http://www.cnblogs.com/cenalulu/p/4325693.html

要了解为什么会出现乱码,我们就先要了解从客户端发起请求,到MySQL存储数据,再到下次从表取回客户端的过程中,哪些环节会有编码/解码的行为。为了更好的解释这个过程,博主制作了两张流程图,分别对应存入和取出两个阶段。

存入MySQL经历的编码转换过程

mysqlflow
上图中有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表中取出数据经历的编码转换过程

mysqlflow
上图有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_clientcharacter_set_connectioncharacter_set_results3个参数值是由客户端每次连接进来设置的,和服务器端没关系。

    我们登陆进mysql后,执行 set names utf8; 实际就是同时修改上面的这3个参数值的。

环境:

    CentOS6.7x86_64

    Percona Server 5.7 (server段设置的是character-set-server= utf8)

在Windows上使用CMD命令行去连接node1,如下图:

wKioL1jzkWqjFMw-AAAig-BuuFY382.png

在Windows上使用SQLyog命令行去连接node1,如下图:

wKioL1jzkWvg80stAAA_btuOlgc242.png

可以看到2个工具连接到同一个服务器上,显示出的参数却不一样的。

从官方文档中可以看出character_set_connection、character_set_client、character_set_results三个字符集什么时候用到。

从实际上可以看到,当客户端连接服务器的时候,它会将自己想要的字符集名称发给mysql服务器,然后服务器就会使用这个字符集去设置character_set_clientcharacter_set_connectioncharacter_set_results这三个值。如cmd是用gbk,而SQLyog是用utf8. 

如果我们想告诉mysql server自己本次连接想使用latin1,则命令行下可以如下写法:

mysql -uroot -h 192.168.2.11 -pAbcd@1234 --default-character-set=latin1

wKiom1jzkZiAG52hAAAq1gwuLeo931.png

此外,要修改上面的3个字符集的话,

还可以在my.cnf的[mysql]段里面增加:

default-character-set=latin1

也可以登录进去后,执行set names latin1的效果相同。

原文地址:https://www.cnblogs.com/silyvin/p/10082736.html