1. 客户端与服务器的连接过程
当我们知道MySQL的架构原理以及启动过程,那么接下来我们就要说一下MySQL的连接过程,以及MySQL是如何对查询语句进行解析并优化的,首先我们回顾一下之前的笔记,讲到 客户端程序和 服务器程序 本质上都是计算机上的一个 进程,所以客户端进程像服务器进程发送请求并得到结果的过程 本质上就是一个进程间通信! MySQL支持三种客户端进程和服务器进程的通信方式.
TCP/IP
当数据库服务器进程和客户端进程运行在不同的主机中,它们之间就必须通过网络来进行通信. MySQL采用TCP作为服务器和客户端之间的网络通信协议.在网络环境下,每台计算机都有一个唯一的IP地址, 如果有进程要用到TCP来进行通信,就可以向操作系统来申请一个端口号, 这是一个整数值, 它的取值范围是0~65535,这样我们的进程就可以通过** IP地址+端口** 的方式来与这个进程连接, 这样进程之间就可以通过网络进行通信了.
MySQL服务器启动的时候会申请3306端口, 意思就是他在这个端口号上等待客户端进程的连接,也就是MySQL服务器会默认监听3306端口.
如果3306被其他进程占用或者我们想自定义端口号,那我们可以在启动服务器程序的命令行里添加-P 来指明一下端口号,注意:-P是大写, 小写代表输入密码.
mysqld -P3307 # 以3307的端口来启动MySQL服务端程序
命名管道和共享内存
如果你是windows用户,那么你可以考虑使用命名管道 或 共享内存进行通信
- 使用命名管道来进行通信
需要在启动服务器程序的命令中加上--enable-named-pipe参数,然后在启动客户端程序的命令中加入--pipe或者--protocol=pipe参数.- 使用共享内存来进行进程间通信
在启动服务器程序的命令中加上--shared-memory参数,在成功启动服务器后, 共享内存便成为本地客户端程序的默认连接方式,不过我们也可以在启动客户端程序时加上protocol=memory参数来显示的指定使用共享内存进行通信,注意:使用共享内存需要服务端和客户端运行在同一台windows主机上.
Unix域套接字文件
暂时还未搞懂,以后在更新,
文章地址:https://juejin.im/book/5bffcbc9f265da614b11b731 第二章
2.服务器处理客户端请求
其实无论是哪种方式进行通信,最后实现流程都是:
1.客户端向服务器发送一段文本(MySQL语句)
- 服务器进程处理后再向客户端进程发送一段文本(处理结果).
那服务器进程对客户端发送的请求进行了那些处理,才能产生最后的处理结果呢? 我们这里放一个图展示一下大致的流程:
从图中我们可以看出,服务器程序处理来自客户端的查询请求大致需要3个部分,分别是连接管理、解析与优化、存储引擎。
连接管理
客户端进程可以采用上面说的这几种方式里进行连接,每当有一个客户端进程连接到服务器进程是,那么服务器就会创建一个线程俩专门处理这个客户端的交互,当该客户端退出时会与服务器断开连接,此时服务器并不会去回收这个线程,而是把这个线程缓存起来,等到下次客户端连接时分派给下一个连接的新客户端,这样就起到了不频繁创建和销毁线程的效果,从而节省开销.所以通过这一点可以开出,每当有客户端连接时,服务器都会为来进行链接的客户端分配一个线程,当然,线程分配过多是会影响到系统性能的,所以我们也需要限制一下可以连接的客户端数量,至于怎么限制,还在学习~
在客户端发起连接时,需要携带主机信息,用户名,密码,服务器程序会对客户端程序提供的信息进行认证,如果认证失败,服务器会拒绝连接,另外,如果服务端和客户端不是在一台计算机上运行的话,我们还可以采用ssl(安全套接字) 的网络连接进行通信,来保证数据传输的安全性.
当连接建立后,与该客户端关联的服务器线程会一直等待客户端发送过来的请求,MySQL服务器接受到的请求只是一个文本信息,改文本信息还要经过各种处理,下面会详细说明~
解析与优化
现在为止,我们已经知道了MySQL服务器获取到了文本形式的请求,接着还要经过一系列的处理,其中比较重要的部分分别是查询缓存、语法解析和查询优化,如下
查询缓存
如果我问你8x9+8的值是多少,你可能会去算第一边,但是我如果第二次问你8x9+8的值是多少,那么你还会去算第二遍吗,显然是不需要,第二次你可以直接告诉我答案。 MySQL服务器处理查询请求也是这样,它会把刚刚的查询请求和结果缓存起来,如果下一次有一模一样的请求过来,直接从缓存重查找结果就好了,就不用再去表中查找了。并且这个查询缓存可以在不同客户端之间共享,也就是说客户端A发送了一个查询请求,而客户端B之后也发送了一个同样的查询请求,南无客户端B的这次查询就可以拿到缓存中的数据。
当然,计算机并没有人那么聪明,如果下一个查询请求有任意一点上的不一样(例如:空格,符号,大小写),都会导致缓存查不到,另外查询请求中的某些函数,用户自定义的变量,系统都不会缓存这次请求,例如NOW,每次请求这个函数都是要求更新当前的时间,如果查询中用到了这个函数,那么即使查询请求一样,都不会缓存,如果第一次查询就缓存了,那么第二次查询直接使用第一次的缓存的结果就是错误的!
既然是缓存,那么就有缓存失效的时候。MySQL的缓存系统会检测每一张表,如果这张表有结构或数据被修改,那么该表的缓存查询就都会变为无效并在缓存中删除!
虽然查询缓存可以提高系统性能,但是也不得不因为这块缓存而造成一些开销,比如每次都要从查询缓存中检索,查询请求处理完需要更新查询缓存,维护该查询对应得内存区域。从MySQL5.7.20开始,不推荐使用查询缓存,并在MySQL 8.0中删除。
语法解析
如果查询缓存没有命中,接下来就需要进入正式得查询阶段了。因为客户端程序发送过来的只是一段文本而已,所以MySQL服务器首先要对这段文本斤做分析,判断请求的语法是否正确,然后从文本中将要查询的表、各种查询条件都提取出来发到MySQL服务器内部使用的一些数据结构上来。
注:从指定文本提取出我们需要的数据算的上是一个编译过程,涉及到词法解析,语法分析,语义分析等,所以我们只需要了解处理请求的过程中需要这个步骤就可以了。
查询优化
语法解析之后,服务器程序获得了需要的信息,比如要查询的列是哪些,表是哪个,搜索条件是什么等等,但是光有这些是不够的,因为我们写的MySQL语句执行起来效率并不高,MySQL的优化程序会对我们的语句做一些优化,例如连接转换为内连接,表达式简化等,优化的结果就是生成一个执行计划,这些计划表明了应该使用哪些索引进行查询,表之间的顺序是什么样的,我们可以使用EXPLAIN语句来查看我们某个语句的执行计划,关于查询优化,后面还在继续研究
存储引擎
一直到查询优化为止,我们还没有真正的去访问真实的数据表,MySQL服务器把数据的存储和提取操作都封装到了一个叫存储引擎的模块里。我们知道表是由一行一行的记录组成的,但是这只是理论上的概念,物理上如何执行,怎么读取数据,怎么把数据写入具体的物理存储器上,这都是存储引擎负责的事情,为了实现不同的功能,MySQL提供了各式各样的存储引擎,不同存储引擎管理的表具体的存储结构可能不同,采用的存取算法也可能不同。
为了管理方便,人们把连接管理、查询缓存、语法解析、查询优化、这些并不涉及真实数据存储的功能划分为MySQL server的功能,把真实存取数据的功能划分为存储引擎的功能。各种不同的存储引擎向上边的MySQL server层提供统一的调用接口(也就是存储引擎API),包含了几十个底层函数,例:"读取索引第一条内容"、"插入记录"等等。
所以在查询优化完成之后,只需要按照生成的执行计划调用底层存储引擎提供的API,获取到数据返回给客户端就好了。
以上就是本次的学习笔记
ps:从根上了解MySQL:https://juejin.im/book/5bffcbc9f265da614b11b731