天天看点

MySQL是怎样运行的

根据我以往的经验,MySQL会启动一个服务,我们可以通过“客户端”链接到服务,进行对数据库的操作。

所以,它的执行步骤通常是这样的:

启动MySQL服务器程序

启动MySQL客户端程序,连接到服务器程序

在客户端程序输入命令语句,并将其作为请求(Http请求???)发送给服务器程序。服务器程序在收到这些请求后,根据请求的内容来操作具体的数据,并将结果返回给客户端。

代表MySQL服务器程序的进程称为MySQL数据库实例

初次启动需要安装,使用<code>mysqld --initialize-insecure</code>,使用<code>console</code>选项可以将安装结果打印在控制台上

如果需要安装服务,使用<code>mysqld --install</code>即可

在命令行中指定启动选项的格式如下:

其中要注意的是启动选项全称前要使用<code>--</code>,单词连接可以使用<code>-</code>或者<code>_</code>,且单词和值之间不要有空格

mysql程序在启动时会在多个路径下寻找配置文件,不过我们一般只需要在<code>basedir</code>,也就是mysql安装目录下防止一份名为<code>my.ini</code>或者<code>my.cnf</code>的配置文件即可

……

由于4字节字符实在不常用(emoji等),所以MySQL默认了两个容易混淆的概念:

utf8mb3:精简的UTF-8字符集,只能表示1~3字节的字符,在MySQL中,utf-8==utf8mb3

utf8mb4:完整的UTF-8字符集能表示1~4字节的字符

所以,如果要在MySQL(版本低于8.0)中存储emoji,要修改MySQL字符集;版本大于8.0后,已经对字符集进行了优化,可以utf-8得以真正地等于utf-8,并且作为数据库的默认字符集出现

通过在控制台输入<code>show charset</code>即可查看当前支持的字符集,可以看到这些字符集都为小写形式出现,值得我们注意的就是最后一列的Maxlen,即最大字符长度

使用<code>show collation</code>命令查看比较规则,但所有字符集的比较规则太多,我们只查看utf8的,<code>show collation where charset like 'utf8';</code>,结果如下,期中Default为Yes的就是该字符集默认的比较规则

这其中的规律是:

“utf8”前缀:表示规则所属的字符集

紧跟前缀:表示规则所应用的语言

“ci”后缀:表示是否区分语言中的重音、大小写等

后缀

全称

含义

<code>_ai</code>

accent insensitive

不区分重音

<code>_as</code>

accent sensitive

区分重音

<code>_ci</code>

case insensitive

不区分大小写

<code>_cs</code>

case sensitive

区分大小写

<code>_bin</code>

binary

以二进制方式比较

示例: <code>utf8_spanish_ci</code> 表示以西班牙语比较,且不区分大小写

MySQL存在4个级别的字符集和比较规则,分别是服务器级别、数据库级别、表级别、列级别

1 服务器级别

MySQL通过两个系统变量来管理服务器级别的字符集和比较规则,通过<code>show variables like 'character_set_server\collation_server';</code>查看这两个变量

系统标量

描述

<code>character_set_server</code>

服务器级别的字符集

<code>collation_server</code>

服务器级别的字符集比较规则

可以通过在ini配置文件中配置这两个变量来制定具体的字符集和规则,

2 数据库级别

在创建和修改数据库时就可以制定该数据库的字符集和比较规则:

在创建完数据并选择中数据库后,可以使用

来查看这两个变量,但是,我们只能通过这两个变量来查看数据库级别的字符集和比较规则,而不能通过这两个变量进行修改

3 表级别

指定方式相同:

既然是表的属性,自然可以通过<code>alter</code>关键字进行修改

4 列级别

制定方式:

修改方式:

要注意的是,在修改字符集和比较规则的时候,如果两个字符集的字符不能相互表示就会引起错误,比如将ASCⅡ的转换成utf8

5 仅修改字符集或者比较规则

只修改字符集,比较规则会自动变成字符集默认的比较规则

只修改比较规则,字符集会变成与之对应的

了解字符集和比较规则后,我们就能够清楚地判断一条记录的实际大小了

对于同一个字符,如果编码和解码使用的字符集不一样就会产生不必要的误解,因此我们需要一套字符集转换的系统:即按照utf8字符集对0xE68891进行解码,随后按照GBK字符集编码成0XCED2,这样就完成了汉字“我”跨字符集的转换。在MySQL中,这样的转换时常发生

MySQL客户端种类繁多,默认的客户端(bin下的mysql程序)使用的字符集和操作系统一致,要查看操作系统的字符集:

UNIX:LC_ALL、LC_CTYPE、LANG这三个环境变量依次决定了系统的字符集

Windows:通过使用命令<code>chcp</code>查看

在Windows下,通过在ini或者在启动命令中指定<code>default-character-set</code>的值来修改客户端默认字符集

本质上说,服务器接收到的请求就是一个字节序列,而它认为这个字节序列的编码就是<code>character_set_client</code>对应的值(每个客户端有单独的值),如果改变这个值,将会产生意料之中的错误:

服务器使用<code>character_set_client</code>指定的字符集来解析字节序列,但真正处理它们还需要将解析后的字节序列转换成由<code>character_set_connection</code>指定的编码后进行。为什么要多加转换的一步呢?

在上面这个例子中,服务器在接收到请求后无法判断这两个字符所处的字符集和比较规则,此时<code>character_set_connection</code>就发挥了作用,上述情况是字符集制定为utf8的情况,下面这种就不一样了:

可以看到,再将连接字符集和比较规则改变后,比较结果就发生了变化。那么问题又来了,客户端不是有一套字符集和比较规则嘛,直接用客户端的不就行了!可有些时候,你会拿字符串和表中的数据进行比较,这时候就需要连接字符集来进行统一了:

表格中的数据是utf8编码的,而客户端发送的请求字节序列确实按照<code>character_set_client</code>指定的,若这个变量的值为gbk,那么这两个字符比较起来就麻烦了,因此,需要统一地将他们转换成优先级更高的字符(在这里就是表中的utf8)

在读取到数据结果后,服务器会根据character_set_results系统变量对应的字符编集进行转换后返回给客户端

客户端会使用客户端默认的字符集来解释这个由服务器返回的字节序列,以下的例子中将返回结果字符集设置成了gbk,而客户端字符集为utf8,于是就产生了乱码!所以,暂且来看,client和result要保持一致

另外,可以通过<code>set names charset_name;</code>来一键配置这三个变量,还可以在ini文件中配置<code>default-character-set</code>来配置这些变量