MySQL是客户端/服务器架构的,那么两边进行通信的过程中肯定会涉及到字符集的处理,因此了解通信过程中客户端和服务器各自是使用什么字符集编码解码是很重要的。
- 一般情况下,客户端对请求进行编码时所使用的字符集和当前操作系统使用的字符集相同,但是如果在MySQL启动时使用
--default-character-set自动选项指定了字符集,则使用该指定的字符集。
在连接服务器时,客户端就会将字符集信息发送给服务器,服务器收到后会将
character_set_client、character_set_connection和character_set_results三个系统变量初始化为客服端发送的字符集。而且三个系统变量在服务器中作用范围都是SESSION级别的,也就是说只作用于当前的连接,不同的连接有不同的值。
- 从客户端发送到服务器的请求实际上是字节序列,那么服务器该如何对该字节序列进行解码呢?这里就会使用到
character_set_client系统变量,服务器则认为该字节序列是使用character_set_client中的字符集编码的。 - 服务器在处理客户端请求的时候,并不是按照客户端的编码使用的字符集,而是使用系统变量
character_set_connection中定义的字符集,因此服务器会先将请求的字符序列转换为character_set_connection中定义的字符集,然后再进行处理。
当遇到类似这种
SELECT * FROM table WHERE c = '我'需要比较列值的情况(应该大多数都是这种情况),MySQL规定,列的字符集和排序规则的优先级更高,也就是这里不会采用character_set_connection中的字符集和比较规则,而是使用该列自身的字符集和比较规则。那什么时候会使用到
character_set_connection呢?比如这种SELECT 'A'='a'没有使用到列值的,就是使用character_set_connection的字符集和比较规则。
-
当服务器处理完之后,返回的给客户端的结果将会是使用
character_set_results中的字符集编码。 -
从服务器返回给客户端的结果也是字节序列,那么客户端又该用什么字符集将其解码显示到屏幕上呢?对于不同系统将会有不同的方式。
- 对于类UNIX操作系统来说,则会默认使用操作系统当前的字符集来解释,如果
character_set_results和客户端所在操作系统的字符集不同,那将会导致解析出现乱码。 - 对于类Windows操作系统来说,则会使用MySQL客户端的默认字符集来解释这个字符。
- 对于类UNIX操作系统来说,则会默认使用操作系统当前的字符集来解释,如果