第一章、初识MySQL
前言:文章是根据《MySQL是怎样运行的:从根儿上理解 MySQL》这本书整理而来,作者小孩子4919,这本书讲的非常透彻,让我开始慢慢理解MySQL底层的一些知识。凭我这极其有限的记忆还是抓紧总结整理一下比较好,要不又要忘干净了......当然自己总结肯定会有很多错误,希望看到的朋友多多指正🤗
第一节、MySQL的架构
MySQL的连接方式其实和微信等很类似。
第二节、MySQL的安装与启动
1、设置环境变量
安装就不说了,我的安装目录如下:
C:\Program Files\MySQL\MySQL Server 5.5
这个目录下有个bin目录,它里面有很多可执行文件,基本都是以.exe为扩展名的。这些文件有的是服务器程序,有的是客户端程序。
作者在这里以macOS为例,windows应该是没有这种困扰。如果想执行某个程序,可以采用相对路径和绝对路径两种方式,但路径都比较长,所以可以配置成环境变量PATH(各个路径以:隔开)。比如mysqld这个程序:
#工作目录在/usr/local/mysql下(macOS种),那么执行bin下的mysqld,相对路径的方式
./bin/mysqld
#绝对路径的方式
/usr/local/mysql/bin/mysqld
#在系统环境变量PATH配置
/usr/local/mysql/bin
#配置好之后直接输入即可启动
mysqld
2、启动服务器程序
这里只介绍windows系统的启动,两种,一种是手动启动,一种是服务的方式启动。手动说白了就是直接点击这个mysqld.exe程序。自然不必多说。
服务的方式启动,先要以管理员的身份打开cmd命令窗口,然后想把某个程序注册到windows的服务可以采用如下的指令:
"完整的可执行文件路径" --install 【-manual】【服务名】
其中manual选项是说这个服务在windows系统刚启动的时候是否自动开启,不写就是自动开启。
先注册到自己的windows服务上,指令如下:
"C:\Program Files\MySQL\MySQL Server 5.5\bin\mysqld" --install
这样就可以使用:
#开启服务器
net start mysql
#关闭服务器
net stop mysql
3、启动客户端程序
这个是比较常见的,就是经常使用的指令:
mysql -h主机名 -u用户名 -p密码
-h:如果是本机的话,可以使用localhost或127.0.0.1;-h是--host的缩写,也可以使用*--host=主机名*的格式;
-u:也可用*-user=用户名*的格式
-p:也可用*-password=密码*的格式,这里当然可以直接使用-p123456这种形式,但是这样就暴露密码了,所以最好-p直接回车,在下面一行隐藏输入密码
关闭使用quit exit \q这三个都行。
第三节、客户端与服务器连接
1、使用tcp/ip协议
客户端和服务器是一个个进程,不难理解客户端和服务器的连接就是进程间的通信。在不同主机下就需要使用网络通信才能连接二者,也就是常用的tcp协议,这里当然也不是重点啦。
这就用到了ip地址 + 端口号来连接了,ip地址就好比哪个楼、哪个单元,端口号就相当于几零几;如果单纯告诉别人我在哪哪个楼哪单元,或者单纯告诉别人我在哪个楼,都不能准确定位到自己的位置。
我们知道MySQL服务器启动时会默认申请3306端口,然后在这个端口等待客户端进行连接,也就是MySQL服务器会默认监听3306端口。(像一只勤奋的小蜘蛛🕷)
当然端口我们也可以自己指定:
mysqld -P端口号
#比如申请3307端口
mysqld -P3307
那么客户端就可以去连接3307端口:
#这里连的还是自己的主机,如果ip地址不是本机可修改
mysql -h127.0.0.1 -uroot -P3307 -p
2、使用命名管道和共享内存
这是针对windows用户的,客户端和服务器进程的通信可以使用命名管道或共享内存,当然这也不是很重要。
- 使用命名管道进行进程通信:需要在启动服务器程序命令中加上--enable-named-pipe参数,然后启动客户端程序的命令中加上--pipe或者--protocol=pipe参数。
- 使用共享内存进行进程间通信:需要在启动服务器程序命令中加上--shared-memory参数。成功启动服务器后,共享内存便成为本地客户端程序的默认连接方式。我们可以在启动客户端程序的命令中加上--protocol=memory参数来显式指定使用共享内存进行通信。而且使用这种方式的服务器和客户端必须位于同一台windows主机中。
第四节、服务器处理客户端的请求
接下来就是本章最核心的一节了。我们总是会很好奇一个机器、程序它的内部到底是如何运行的,我们到底为什么在MySQL客户端输入sql指令,就能从数据库中拿到我们想查的数据呢?这一节可以让我们有一个初步的认识。
看上面这个图,其实MySQL服务器处理请求大概就是这三部分。每个部分的名字都很好的总结了它们的作用。
1、连接管理
每当一个客户端连接到服务器,服务器进程都会启动一个线程来与客户端进行交互;客户端断开连接时,不是直接关闭线程,而是把这个线程缓存起来,如果有另外的连接进入,那么把这个缓存的线程分配给新的客户端。这样就避免无意义的频繁创建线程。
在客户端发起连接时,需要携带很多信息,比如主机信息、用户名、密码等,服务器会进行认证,成功才能连接。而且如果不是同一台主机,还需要满足网络的协议才行。
连接好以后,服务器就处于一直等待客户端发信息的状态。服务器接收到客户端发来的请求,这个请求相当于只是一个文本消息,需要经过很多处理。
2、解析与优化
(1)查询缓存
客户端发送请求后,服务器拿到了文本消息,还要进行解析与优化的相关步骤。第一步就是查询缓存。
比如一个请求经过一系列操作以后查到了结果,如果再查一遍还要这么多步骤吗?其实不用,MySQL服务器会把这条请求和查询结果进行缓存,然后下次先去缓存中查,如果有结果,那么就直接返回即可。这个查询缓存时可以在不同客户端之间共享的。
但计算机不可能那么智能,写了一条select查询语句,被放入了查询缓存中,第二次还是这条select语句,我添加了空格、注释,改变了语句大小写,鬼知道你这个是不是之前那一条语句?所以这个请求比较苛刻,必须**要求这两条语句必须一致**,不能修改空格、注释、大小写等信息。
另外还有**一些函数可能不能使用缓存**,比如我有这样的语句:
select now();
然后缓存起来,下次查询now()函数,得到的是哪个时间呢?肯定是当前时间。这个是不会缓存的。
另外就是**对表进行了修改,那么缓存也会失效**,比如使用了insert、update、delete、truncate table、alter table、drop table、drop database等语句,之前的缓存都会被删除掉。
从MySQL5.7.20开始,不推荐使用查询缓存,MySQL8.0中甚至直接删除了查询缓存。
(2)语法解析
查询缓存中没有,那么就该直接查询了。首先MySQL服务器会先**判断sql语句的语法是否正确**。
然后会**从这个文本信息中提取要查询的表、查询条件等,把他们放入MySQL服务器内部使用的一些数据结构上**。
(3)查询优化
服务器拿到这些信息后,服务器会帮我们**做一些优化,生成一个执行计划**,执行计划表名了使用哪些索引来执行这个查询,以及表之间的连接顺序等等。
我们可以使用explain来查询某个语句的执行计划。下面只是一个简单的示例。
3、存储引擎
上面这些步骤只是帮我们进行一些准备,下面才是真正去访问表中的数据。MySQL中表都存于存储引擎中。存储引擎其实通俗一点的名字叫做表处理器。
存储引擎其实只是在物理上如何表示记录,怎么从表中读取数据,怎么把数据写入具体的物理存储器上有所不同。不同的存储引擎可能有不同的存储结构和算法。
人们通常把MySQL服务器处理请求的过程分两层——server层和存储引擎层。连接管理、查询缓存、语法解析、查询优化等这些和真实数据不交互的划分到server层,存取真实数据在存储引擎层。
我们比较常用的存储引擎是InnoDB、MyISAM、Memory这三个,其中InnoDB是默认的存储引擎。
第五节、存储引擎常用指令
查看当前服务器支持的存储引擎:
show engines;
这里比较重要的列:support表示当前存储引擎是否可用,comment是简介,transaction事务,xa表示是否支持分布式事务,savepoint表示是否支持部分回滚(是否可以设置保存点)。
设置修改表的存储引擎:
#设置
create table 表名{
建表语句;
}engine = 存储引擎名;
#修改
alter table 表名 engine = 存储引擎名;