彻底解决MySQL中的乱码问题( 五 )


  • 对于UNIX操作系统来说,MySQL客户端向黑框框中写入数据使用的是操作系统提供的 fputs 、 putc 或者 fwrite 函数,这些函数基本上相当于直接就把接收到的字节序列写到了黑框框中(请注意我们用词: '基本上相当于',其实内部还会做一些工作,但是我们这里就不想再关注这些细节了) 。此时如果该字节序列实际的字符集和黑框框展示字符所使用的字符集不一致的话,就会发生所谓的乱码(大家注意,这个时候和操作系统当前使用的字符集没啥关系) 。比方说我们在启动MySQL客户端的时候使用了 --default-character-set=gbk 的启动参数,那么服务器的 character_set_result 变量就是gbk 。然后再执行 SELECT * FROM t 语句,那么服务器就会将字符 '我' 的gbk编码,也就是 0xCDE2 发送到客户端,客户端直接把这个字节序列写到黑框框中,如果黑框框此时采用utf8字符集展示字符,那自然就会发生乱码 。
  • 对于Windows操作系统来说,MySQL客户端向黑框框中写入数据使用的是操作系统提供的 WriteConsoleW 函数,该函数接收一个宽字符数组,所以MySQL客户端调用它的时候需要显式地将它从服务器收到的字节序列按照客户端默认的字符集转换成一个宽字符数组 。正因为这一步骤的存在,所以可以避免上边提到的一个问题 。比方说我们在启动MySQL客户端的时候使用了 --default-character-set=gbk 的启动参数,那么服务器的 character_set_result 变量就是gbk 。然后再执行 SELECT * FROM t 语句,那么服务器就会将字符 '我' 的gbk编码,也就是 0xCDE2 发送到客户端,客户端将这个字节序列先从客户端默认字符集,也就是gbk的编码转换成一个宽字符数组,然后再调用 WriteConsoleW 函数写到黑框框,黑框框自然可以把它显示出来 。
乱码问题应该如何分析好了,介绍了各个步骤中涉及到的各种字符集,大家估计也看的眼花缭乱了,下边总结一下我们遇到乱码的时候应该如何分析,而不是胡子眉毛一把抓,随便百度一篇文章,然后修改某个参数,运气好修改了之后改对了,运气不好改了一天也改不好 。知其然也要知其所以然,在学习了本篇文章后,大家一定要有节奏的去分析乱码问题:
  • 我使用的是什么操作系统
    • 对于UNIX系统用户来说,要搞清楚我使用的黑框框到底是使用什么字符集展示字符,就像是 iTerm2 中的 character encoding 属性:同样还要搞清楚操作系统当前使用什么字符集,运行 locale 命令查看:王大爷喊你输入呢,跟这儿>locale LANG="" LC_COLLATE="zh_CN.UTF-8" LC_CTYPE="zh_CN.UTF-8" LC_MESSAGES="zh_CN.UTF-8" LC_MONETARY="zh_CN.UTF-8" LC_NUMERIC="zh_CN.UTF-8" LC_TIME="zh_CN.UTF-8" LC_ALL="zh_CN.UTF-8" 王大爷喊你输入呢,跟这儿>没有什么特别极端的特殊需求的话,一定要保证上述两个字符集是相同的,否则可能连汉字都输入不进去!
    • 对于Windows用户来说搞清楚自己使用的黑框框的代码页是什么,也就是操作系统当前使用的字符集是什么 。
  • 搞清楚客户端的默认字符集是什么启动MySQL客户端的时候有没有携带 --default-character-set 参数,如果携带了,那么客户端默认字符集就以该参数指定的值为准 。否则分析自己操作系统当前使用的字符集是什么 。
  • 搞清楚客户端发送请求时是以什么字符集编码请求的
    • 对于UNIX系统来说,我们可以认为请求就是采用操作系统当前使用的字符集进行编码的 。
    • 对于Windows系统来说,我们可以认为请求就是采用客户端默认字符集进行编码的 。
  • 通过执行 SHOW VARIABLES LIKE 'character%' 命令搞清楚:
    • character_set_client :服务器是怎样认为客户端发送过来的请求是采用何种字符集编码的
    • character_set_connection :服务器在运行过程中会采用何种字符集编码请求中的字符
    • character_set_result :服务器会将响应使用何种字符集编码后再发送给客户端的
  • 客户端收到响应之后:对于服务器发送过来的字节序列来说:
    • 在UNIX操作系统上,可以认为会把该字节序列直接写到黑框框里 。此时应该搞清楚我们的黑框框到底是采用何种字符集展示数据 。
    • 在Windows操作系统上,该字节序列会被认为是由客户端字符集编码的数据,然后再转换成宽字符数组写入到黑框框中 。

【彻底解决MySQL中的乱码问题】


推荐阅读