mysql底层机制
>MySQL的分层可以分为Service层和引擎层。下图就是MySQL8之前的执行流程。
执行流程
当我们客户端向mysql server发起连接的时候会先通过连接器去进行身份认证,认证成功后才可以连接。当我们在查询一条数据的时候,它首先会去查询缓存(在MySQL8的时候被取消了),如果缓存中有相应的SQL和数据就会直接将数据返回,如果没有则会对这条SQL进行解析,解析完成后再对这条SQL 进行优化最后再到达存储引擎,执行这条命令。
连接器
那么什么是连接器呢?见名知意,当我们的客户端和服务端进行交互的时候,服务端就会创建一个线程去和这个客户端专门去做交互。当我们使用下面这条命令去连接数据库的时候:
mysql -h127.0.0.1 -P3306 -uroot -proot
它会带上你想要连接的主机号、端口、账户和密码等信息进行认证,如果没有在权限表中查找相应的权限就会refused这条连接,如果找到的话就会进入到连接器中,连接器会给这条连接创建一个线程。在MySQL中的连接有长链接和短链接两种方式。
- 长链接:连接成功后,如果客户端持续请求就会一直用一个链接。
- 短链接:执行几次后就会自动断开,下次查的时候会继续创建一个链接。
我们一般常用于长连接,因为建立连接的过程是一个非常复杂且消耗资源的过程。但是我们全部用长链接之后就会发现MySQL占用内存涨的比较快,这是因为长连接长期积累会导致占用的内存过大,只有等连接断开后才会释放资源。
每一次创建链接就是一个创建线程的过程,为了不频繁的让线程创建、销毁,连接器中有一个连接池的概念,它可以将创建的线程缓存下来,这样就可以避免频繁的去创建销毁线程。
我们不能创建太多的线程,如果有1000W条连接进来,我们就要创建1000W个线程嘛?所以我们就必须去限制这个连接数量。
查询缓存
当MySQL接收到了一个查询请求的时候,它并不会先去存储引擎中查找,而是先看缓存中是否存在,之前查询的语句会以k-v的形式被缓存起来,当我们输入一模一样的查询语句的时候它会直接在这返回结果,这样也提高了查询效率。是不是看起来很美好?不过这一切只是看起来而已,它有一些让你头疼不已的缺点。
- 它必须是一模一样的语句,不然你多个空格,少个空格都不会在缓存中找到。
- 有些函数是即时性的,比如说Now(),两次查询的时间是不一样的。
- 缓存失效,当数据有了更改之后就会失效。
- 我们需要开辟一块空间去专门维护这个功能,增加了维护难度。
根据以上的种种原因,缓存这个空间在MySQL8的时候被干掉了。
语法解析
我们在输入一条语句的时候,它肯定会有一个解析的过程。这里的语法解析就相当于编译阶段的词法解析、语法分析和语义分析,如果这三个阶段无法过去,就是说你输入的语句有错误就会直接报错。
select * form table; //类似于这种的就会直接报错
优化
到了这个阶段就说明,你写的SQL语法是没问题的,但是并不代表着你写的SQL很好,很节省时间。这里就是去优化你的SQL,当表中有多个索引的时候,决定使用哪个索引或者在一条语句关联了多张表的时候,各个表的连接顺序。因为有时候结果相同,但是效率不同,优化器就是尽量选择效率比较好的方式。
操作引擎
前面那一长串都是为了去对你的SQL文本进行优化的,但是并没有去真正的执行这条SQL,到了这一步了,它才会用SQL操作存储引擎。
存储引擎
这里才是数据存储的地方,也是SQL真正的去执行的地方。常见的存储引擎基本就是InnoDB和MyIsam这两种存储引擎。在MySQL5.7之后,我们创建表默认的引擎就是InnoDB,因为InnoDB相对于MyISAM来说,它更支持事务、行级锁、B+树存储、外键、聚集索引
等操作。
参考资料
极客时间——MySQL45讲中01 | 基础架构:一条SQL查询语句是如何执行的?
掘金小册——MySQL是怎样运行的:从根儿上理解MySQL