字符集转换概述
我们有必要说明一下,字符 其实是面向人类的一个概念,计算机可并不关心字符是什么,它只关心这个字符对应的字节编码是什么 。对于一个字节序列,计算机怎么知道它是使用什么字符集编码的呢?计算机不知道,所以其实在计算机中表示一个字符串时,都需要附带上它对应的字符集是什么,就像这样(以C++语言为例):
class String {byte* content;CHARSET_INFO* charset;}比方说我们现在有一个以 utf8 字符集编码的汉字 '我',那么意味着计算机中不仅仅要存储 '我' 的utf8编码 0xE68891,还需要存储它是使用什么字符集编码的信息,就像这样:
{content: 0xE68891;charset: utf8;}计算机内部包含将一种字符集转换成另一种字符集的函数库,也就是某个字符在某种字符集下的编码可以很顺利的转换为另一种字符集的编码,我们将这个过程称之为 字符集转换。比方说我们可以将上述采用utf8字符集编码的字符'我',转换成gbk字符集编码的形式,就变成了这样:
{content: 0xCED2;charset: gbk;}小贴士:我们上边所说的'编码'可以当作动词,也可以当作名词来理解 。当作动词的话意味着将一个字符映射到一个字节序列的过程,当作名词的话意味着一个字符对应的字节序列 。大家根据上下文理解'编码'的含义 。
MySQL客户端和服务器是怎么通信的MySQL客户端发送给服务器的请求以及服务器发送给客户端的响应其实都是遵从一定格式的,我们把它们通信过程中事先规定好的数据格式称之为MySQL通信协议,这个协议是公开的,我们可以简单的使用wireshark等截包软件十分方便的分析这个通信协议 。在了解了这个通信协议之后,我们甚至可以动手制作自己的客户端软件 。市面上的MySQL客户端软件多种多样,我们并不想各个都分析一下,现在只选取在MySQL安装目录的 bin 目录下自带的 mysql 程序(此处的 mysql 程序指的是名字叫做 mysql 的一个可执行文件),如图所示:
我们在计算机的黑框框中执行该可执行文件,就相当于启动了一个客户端,就像这样:

文章插图
小贴士:我们这里的'黑框框'指的是windows操作系统中的cmd.exe或者UNIX系统中的Shell 。
我们通常是按照下述步骤使用MySQL的:
- 启动客户端并连接到服务器
- 客户端发送请求 。
- 服务器接收到请求
- 服务器处理请求
- 服务器处理请求完毕生成对该客户端的响应
- 客户端接收到响应
启动客户端并连接到服务器过程每个MySQL客户端都维护者一个客户端默认字符集,这个默认字符集按照下边的套路进行取值:
- 自动检测操作系统使用的字符集MySQL客户端会在启动时检测操作系统当前使用的字符集,并按照一定规则映射成为MySQL支持的一些字符集(通常是操作系统当前使用什么字符集,就映射为什么字符集,有一些特殊情况,比方说如果操作系统当前使用的是ascii字符集,会被映射为latin1字符集) 。
- 当我们使用UNIX操作系统时此时会调用操作系统提供的 nl_langinfo(CODESET) 函数来获取操作系统当前正在使用的字符集,而这个函数的结果是依赖 LC_ALL 、 LC_CTYPE 、 LANG 这三个环境变量的 。其中 LC_ALL 的优先级比 LC_CTYPE 高,LC_CTYPE 的优先级比 LANG 高 。也就是说如果设置了 LC_ALL,不论有没有设置 LC_CTYPE 或者 LANG,最终都以 LC_ALL 为准;如果没有设置 LC_ALL,那么就以 LC_CTYPE 为准;如果既没有设置 LC_ALL 也没有设置 LC_CTYPE,就以 LANG 为准 。比方说我们将环境变量 LC_ALL 设置为 zh_CN.UTF-8,就像这样:export LC_ALL=zh_CN.UTF-8 那么我们在黑框框里启动MySQL客户端时,MySQL客户端就会检测到这个操作系统使用的是 utf8 字符集,并将客户端默认字符集设置为 utf8。当然,如果这三个环境变量都没有设置,那么 nl_langinfo(CODESET) 函数将返回操作系统默认的字符集,比方说在我的 macOS 10.15.3 操作系统中,该默认字符集为:US-ASCII 此时MySQL客户端的默认字符集将会被设置为 latin1。另外,我们这里还需要强调一下,我们使用的黑框框展示字符的时候有一个自己特有的字符集,比如在我的mac上使用 iTerm2 作为黑框框,我们可以打开:Preferences->Profiles->Terminal选项卡,可以看到 iTerm2 使用 utf8 来展示字符:我们一般要把黑框框展示字符时采用的编码和操作系统当前使用的编码保持一致,如果不一致的话,我们敲击的字符可能都无法显示到屏幕上 。比方说如果我此时把 LC_ALL 属性设置成 GBK,那么我们再向黑框框上输入汉字的话,屏幕都不会显示了,就像这样(如下图所示,我敲击了汉字 '我' 的效果):
推荐阅读
- Linux环境下MySQL安装
- 在MySQL官网下载安装数据库
- 非常重要的mysql数据库定时备份!
- mysql5.7 使用XtraBackup2.4 全量备份还原
- 染发剂中的3.0或4.0是什么意思?了解颜色代码,染啥颜色一目了然
- 西游记中的歇后语 白骨精给唐僧送饭的歇后语
- 请收好Netcat网络工具中的瑞士军刀,从此故障诊断不用愁!
- URI中的 “//” 有什么用?
- 末影龙能打败凋零吗?
- 观察中的发现作文示例5篇 观察中的发现作文
- 当我们使用UNIX操作系统时此时会调用操作系统提供的 nl_langinfo(CODESET) 函数来获取操作系统当前正在使用的字符集,而这个函数的结果是依赖 LC_ALL 、 LC_CTYPE 、 LANG 这三个环境变量的 。其中 LC_ALL 的优先级比 LC_CTYPE 高,LC_CTYPE 的优先级比 LANG 高 。也就是说如果设置了 LC_ALL,不论有没有设置 LC_CTYPE 或者 LANG,最终都以 LC_ALL 为准;如果没有设置 LC_ALL,那么就以 LC_CTYPE 为准;如果既没有设置 LC_ALL 也没有设置 LC_CTYPE,就以 LANG 为准 。比方说我们将环境变量 LC_ALL 设置为 zh_CN.UTF-8,就像这样:export LC_ALL=zh_CN.UTF-8 那么我们在黑框框里启动MySQL客户端时,MySQL客户端就会检测到这个操作系统使用的是 utf8 字符集,并将客户端默认字符集设置为 utf8。当然,如果这三个环境变量都没有设置,那么 nl_langinfo(CODESET) 函数将返回操作系统默认的字符集,比方说在我的 macOS 10.15.3 操作系统中,该默认字符集为:US-ASCII 此时MySQL客户端的默认字符集将会被设置为 latin1。另外,我们这里还需要强调一下,我们使用的黑框框展示字符的时候有一个自己特有的字符集,比如在我的mac上使用 iTerm2 作为黑框框,我们可以打开:Preferences->Profiles->Terminal选项卡,可以看到 iTerm2 使用 utf8 来展示字符:我们一般要把黑框框展示字符时采用的编码和操作系统当前使用的编码保持一致,如果不一致的话,我们敲击的字符可能都无法显示到屏幕上 。比方说如果我此时把 LC_ALL 属性设置成 GBK,那么我们再向黑框框上输入汉字的话,屏幕都不会显示了,就像这样(如下图所示,我敲击了汉字 '我' 的效果):
