mysql整体架构和语句的执行流程

首页 / MySql / 正文

mysql服务端整体架构

image-20220625103943720.png

主要分为两部分,server层存储引擎

  • server层包括连接器查询缓存分析器优化器执行器等,涵盖mysql的大多数核心服务过功能,以及所有的内置函数,所有跨存储引擎的功能都在这一层实现,比如存储过程,触发器,视图等
  • 存储引擎层负责数据等存储和读取,其架构模式是插件式的,支持InnoDBMyISAM等多个引擎。从mysql5.5.5版本开始InnoDB成为了默认引擎。

MySql查询流程

由mysql客户端发起请求,连接器负责与客户端连接验证权限,连接成功之后开始查询缓存(当缓存开启时),如果命中则直接返回数据,如果没有命中则交由分析器进行sql词法和语法分析,然后交给优化器进行选择索引生成执行计划,最后交给执行器去调用存储引擎的API获取结果并返回

查询缓存

当 MySQL 服务端拿到一条 SQL 查询语句后,首先会查询缓存,看之前是不是执行过这条语句。如果执行过,会缓存在内存中,这个时候直接返回之前缓存的查询结果给客户端即可;如果在缓存中没有找到对应的记录,就会继续后面的操作,并且在最终执行完成后,将查询结果保存到查询缓存。

注:MySQL 8.0 版本开始将不再支持查询缓存功能。

可以通过show variables like '%query_cache%';语句查看系统查询缓存的设置

query_cache_typeOFF 表示默认关闭。你可以在配置文件中配置该值来决定是否启用查询缓存。

分析器

如果查询缓存没有启用或者没有命中,就开始真正执行 SQL 查询语句了。

MySQL 会通过分析器对 SQL 语句做词法分析,以确定到底要做什么,比如 select 表示查询语句,update 表示更新语句等,表名是什么,查询的字段有哪些,查询的条件是什么。

优化器

如果 SQL 语句词法和语法分析都没有问题,接下来,会经由优化器生成执行计划,这里面主要的工作是数据表包含索引的时候,判定是否使用索引,以及使用哪些索引效率最高(扫描行数最少),我们可以在执行一个 SQL 查询语句之前通过 explain 语句查看它的执行计划:

执行器

根据执行计划执行sql查询语句时,会先验证权限,有相应权限才会继续执行,否则会报权限错误

具体的查询操作是通过存储引擎提供的API接口完成的。执行器调用这些接口可以完成诸如读取下一行记录、插入记录、更新记录之类的日常数据库操作,执行 SQL 查询返回所有满足条件的结果集也是如此。

SQL更新语句执行流程与日志写入

和sql查询语句一样,MySql客户端提交SQL更新语句前,先要通过连接器建立连接,连接器验证权限等相关操作,然后交给分析器进行词法和语法分析后由执行器负责具体的执行。(修改、删除语句也是一样)

当一张数据表有更新的时候,对应的查询缓存数据就会被清空。

与查询流程不一样的是,更新还涉及到日志的写入,redo log(重做日志)和binlog(归档日志)

日志写入

MySql的设计者引入了WAL技术(Write-Ahead Logging),即先写日志,在写磁盘。

比如InnoDB引擎,当有记录需要更新的时候,InnoDB就会先把记录写到redolog里边,并更新内存,这时候更新操作就算是完成,等InnoDB空闲的时候,在将这个操作更新到磁盘里边。这样做就是因为如果每次更新操作都要写到磁盘的话,整个IO成本会非常高。

redo log

redo Log 是InnoDB引擎提供的日志系统,bindlog可以一直追加写入,负责数据库全量数据的备份和恢复,数据库集群的主从同步也是基于binlog实现的。

binlog

binlog是属于MySql Server层面的,所有存储引擎都可以共用它

在 InnoDB 引擎出现之前,MySQL 默认的存储引擎是 MyISAM,那个时候为了实现数据备份和恢复,使用的是 binlog,不过 binlog 是一个归档日志,不具备数据库崩溃重启后的数据恢复功能

两个日志的写入流程

  1. 执行器通过 API 接口将更新数据传递给存储引擎执行更新操作;
  2. 存储引擎在拿到更新数据后,先将其更新到内存,同时将这个更新操作记录到 redo log,此时 redo log 处于 prepare 状态,然后告知执行器执行完成了,随时可以提交事务;
  3. 执行器生成这个操作的 binlog,并把 binlog 写入磁盘(写入时机可以配置,对于事务操作而言,都是在事务提交时才会持久化写入的,相关细节我们后面讲数据库数据一致性的时候会详细介绍);
  4. 执行器调用引擎的提交事务接口,引擎把刚刚写入的 redo log 改成 commit 状态,更新完成。

f6ccb6f1139cd934f336369a5bb7e2af.png

在上述步骤中,将 redo log 的写入拆成了两个步骤:preparecommit,这就是「两阶段提交」。

如果不使用两阶段提交,会导致两份日志恢复的数据不一致:比如先写 redo log,binlog 还没有写入,数据库崩溃重启;或者先写 binlog,redo 还没有写入数据库崩溃重启,都将造成恢复数据的不一致。

而使用两阶段提交后,就可以保证两份日志恢复的数据一致:只有 binlog 写入成功的情况下,才会提交 redo log,否则 redo log 处于 prepare 状态,事务会回滚,这样一来,就保证了数据的一致性。

打赏
评论区
头像
    头像

    2025年10月新盘 做第一批吃螃蟹的人coinsrore.com
    新车新盘 嘎嘎稳 嘎嘎靠谱coinsrore.com
    新车首发,新的一年,只带想赚米的人coinsrore.com
    新盘 上车集合 留下 我要发发 立马进裙coinsrore.com
    做了几十年的项目 我总结了最好的一个盘(纯干货)coinsrore.com
    新车上路,只带前10个人coinsrore.com
    新盘首开 新盘首开 征召客户!!!coinsrore.com
    新项目准备上线,寻找志同道合 的合作伙伴coinsrore.com
    新车即将上线 真正的项目,期待你的参与coinsrore.com
    新盘新项目,不再等待,现在就是最佳上车机会!coinsrore.com
    新盘新盘 这个月刚上新盘 新车第一个吃螃蟹!coinsrore.com

文章目录