接上一篇,讨论这三者
character_set_client
character_set_connection
character_set_results
1
给出一个结论:character_set_results只是显示相关,不影响任何的插入,当正确的插入了中文字符串:例如“啊”,只要character_set_results与cmd的编码格式一致,就不会出现乱码
问题简化到character_set_client 与character_set_connection之间的关系
2
然后在如下配置启动 mysqld 服务器程序
[mysql]
default-character-set=utf8
[mysqld]
character-set-server=utf8
然后启动四个mysql客户端程序,动态的set字符集,如下:
四个窗口序号为1234;(把所有的results设置为gbk,保证所有窗口的select一致,不会因为混乱导致错误的推断)
3
在cmd编码为gbk的情况下,四个窗口执行 mysql> insert into test(name,age) values('啊',22);
窗口1,2的insert结果,能够被select正确的字符串,窗口三会报错
ERROR 1366 (HY000): Incorrect string value: '\xB0\xA1' for column 'name' at row 1
窗口4的执行结果被查询为乱码;
我最初对character_set_client 与character_set_connection的定位是:
mysql客户端会将请求(cmd的gbk编码请求)转码为character_set_client的格式,发送给服务器;服务器接收到后会把character_set_client的格式转化为character_set_connection的格式;
产生的一系列问题,
(1)窗口1的character_set_connection为什么是gbk?(如果把配置中mysql 的 default-character-set=gbk,那么打开的mysql客户端的client与connection会默认为一致的gbk),而我最初预期的是,connection应该是与server一致的utf8。
(2)窗口2是我理想中 的正确配置,但是2与1的执行结果是一致的,都正确,意味着character_set_connection的改动没有生效?
(3)窗口3为什么会报错:character_set_client不是应该将cmd的编码转换过了么。报错是来自于那一层:client转换,connection转换或者实际的server插入操作?
(4)窗口4的编码格式错误;出自哪一步?
思考的过程是复杂的:(想太多自己都忘记思考过程了),推测:
(1)在某个瞬间,突然产生一个猜测:窗口3:因为除cmd编码为gbk之外。其他(可见的)配置都是utf8,所以在整个过程中没有执行任何的编码转换过程,这导致一个sb的结果。来自cmd的gbk编码请求,被直接应用到了server的执行层。mysql客户端并没有处理来自cmd的编码异常。服务器报错
(2)结合窗口4的乱码结果,由此得出第二个猜测:character_set_client的定义并不是一个转码配置,而是告知服务端,客户端送出的client的格式是xxx。类似于通信协议的包头。而这种操作的直接结果就是:当cmd的编码格式是gbk而character_set_client=utf8时,错误就产生了,客户端的实际编码与声明编码不一致:
(3)那么为什么窗口3是报错,而窗口4是乱码呢?这就涉及到character_set_connection了,猜测character_set_connection的定义是,将来自客户端的任何请求的编码格式,转化为character_set_connection的编码格式(神奇操作2:如果character_set_connection与character_set_client一致,就不执行转码,这就是窗口3的错误编码----畅通无阻的运行到server的原因)窗口4:虽然有一个错误的编码声明,但是由此转换了一步编码,转为gbk。而server层会隐式的有自己的转码步骤,将gbk转为server的utf8然后执行,所以窗口4能执行,只是乱码。
结论:
(1)character_set_client的定义并不是一个转码配置,而是告知服务端,客户端送出的client的格式是xxx。
(2)character_set_connection的定义是,将来自客户端的任何请求的编码格式,转化为character_set_connection的编码格式(但是如果character_set_connection与character_set_client一致,就不执行转码)
测试:
新开窗口5,将配置set为
用这两个进行测试。符合推测