mysql客户端是如何与服务端通信的?1、首先,请求会被MySQL客户端编码成字节序列,然后通过网络传输给服务器端。对于MySQL自带的客户端,这个编码过程使用的字符集和我们使用的操作系统的默认字符集是一样的。类Unix系统默认的字符集是utf8,Windows系统默认的字符集是gbk。MySQL客户端启动时,MySQL客户端会检测到操作系统使用的是utf8字符集,并设置客户端的默认字符集为utf8。如果MySQL不支持操作系统当前使用的自动检测字符集,或者某些情况下不允许自动检测,则MySQL使用自己内置的默认字符集作为客户端默认字符集。内置默认字符集在MySQL5.7及更早版本中为latin1,在MySQL8.0中改为utf8mb4。如果我们在启动MySQL客户端时使用default-character-set启动参数,则客户端的默认字符集将不再检测操作系统当前使用的字符集,而是直接使用启动参数default-character-set指定值。比如我们使用如下命令启动客户端:mysql--default-character-set=utf8那么无论我们使用什么操作系统,操作系统当前使用什么字符集,我们都会默认使用utf8MySQL客户端字符集。2、服务端收到字节序列请求后,会认为字节串是根据character_set_client系统变量进行编码的,然后将其从character_set_client转换为character_set_connection进行进一步处理。3.最后,当response发送给client时,会根据character_set_results进行编码。4、客户端收到响应字节串后,根据客户端指定的字符集进行解码。对于MySQL自带的客户端,这个解码过程使用的字符集和我们使用的操作系统的默认字符集是一样的。类Unix系统默认的字符集是utf8,Windows系统默认的字符集是gbk。系统变量说明MySQL客户端字符集MySQL客户端字符集character_set_client服务器解码请求时使用的字符集(服务器认为请求是根据系统变量指定的字符集编码的)character_set_connection服务器处理请求时,它会将请求字符串从character_set_client转换为character_set_connectioncharacter_set_results服务器向客户端返回数据时使用的字符集(服务器使用系统变量指定的字符集对返回给客户端的字符串进行编码)通信转码过程中,需要保证没有乱码:character_set_clientcharacter_set_connection和character_set_result三个系统变量要与客户端默认字符集相同。SETnames命令可以同时修改这三个系统变量。实验验证数据库字符集:1.客户端发送请求时,字符'I'会按照utf8进行编码,即:0xE68891。2、服务端收到请求,找到前缀_gbk后,不再对后面的字符进行编码0xE68891段由character_set_client转为character_set_connection,而是直接将0xE68891视为一个字符串经过gbk编码得到的字节序列。3、然后把上面的0xE68891从gbk转成character_set_results,也就是utf8。0xE688表示gbk中的汉字'鎴',0x91无法解码(我们可以看到上面的查询结果有warning)。结语解决乱码问题,需要从客户端到服务端通信过程中的字符集编码、转码、解码,分析是哪一步出了问题。一般情况下,保证:character_set_clientcharacter_set_resultscharacter_set_connection客户端的字符集编码一致时,就可以解决乱码问题。
