0
点赞
收藏
分享

微信扫一扫

程序员的实用神器

小迁不秃头 2024-05-07 阅读 9

在这里插入图片描述

文章目录

11.一条SQL语句在MySQL的执行过程

11.1MySQL整体架构

image-20240502163558086

MySQL 逻辑架构图主要分三层:

  • 客户端:最上层的服务并不是 MySQL 所独有的,大多数基于网络的客户端/服务器的工具或者服务都有类似的架构。比如连接处理、授权认证、安全等等
  • Server 层:大多数 MySQL 的核心服务功能都在这一层,包括查询解析、分析、优化、缓存(MySQL8版本后移除)以及所有的内置函数(例如,日期、时间、数学和加密函数),所有跨存储引擎的功能都在这一层实现:存储过程、触发器、视图等。
  • 存储引擎层:第三层包含了存储引擎。存储引擎负责 MySQL 中数据的存储和提取。Server 层通过 API 与存储引擎进行通信。这些接口屏蔽了不同存储引擎之间的差异,使得这些差异对上层的查询过程透明。

11.2SQL语句在Server层执行流程

  • 下面我们分析一下一条查询语句的执行流程
select user_id、username 
from t_user 
where username = "张三" and sex = 1
  • 总结SQL语句执行流程:权限校验—》查询缓存—》分析器—》优化器—》权限校验—》执行器—》引擎

11.3拓展:InnoDB存储引擎的更新操作

上面介绍的是查询语句执行流程,而一条更新语句的的查询过程基本是沿用上面的步骤,但在更新的时候要记录日志。下面我们来探索一下在InnoDB存储引擎是如何保证更新语句的成功执行。以下面语句为例(user_id=1这条记录原始值为“张三”)。

update t_user set username = "李四" where user_id = 1
  1. InnoDB会先去BufferPool中去查找user_id=1的数据,没找到就会去磁盘中查找,如果查找到就会将这条记录加载到缓冲池BufferPool中,由于是更新操作,InnoDB会对这条记录加锁。

  2. 我们都知道SQL语句执行前默认是开启事务的,考虑到更新失败后的数据回滚,把更新前的数据写入undolog中

  3. 更新缓存池BufferPool的值为“李四”

    在这里插入图片描述

  4. 此时内存中的数据已经修改,但磁盘中的数据还未更新,为避免数据的丢失,需要把更新的值写入redo log Buffer中,

  5. 此时就可以准备事务的提交了,提交事务的同时会根据一定策略把redo log从buffer中刷入磁盘。此时若MySQL崩溃,重启可根据redo log日志把数据重新写入BufferPool中,避免了数据的丢失。此时redo log 处于 prepare 状态

在这里插入图片描述

  1. 到这里InnoDB层面的操作就差不多了,接下来执行器会生成更新操作的 binlog,并把binlog 日志写入磁盘
  2. 把本次更新的binlog文件名称和本次更新的binlog日志在文件里面的位置,都写入到redo日志文件中,同时在redo log日志中打上一个commit标记。此时redo log 处于 commit 状态。至此,事务提交成功
  3. 事务提交成功后,后台会另起io线程把脏数据刷入磁盘中。

在这里插入图片描述

11.3.1问题:为什么写了redolog日志还要写binlog日志?

​ 性质不同

  • redolog是InnoDB独有的,文件大小有限,主要用于崩溃恢复
  • binlog是MySQL层面的日志,通过追加的方式记录,主要用于主从复制和数据恢复

11.3.2问题:为什么要两阶段提交?

我们看到redolog的提交分为两阶段,prepare和commit。为什么不先写binlog呢?

  • 原因:
    • 第5步和第6步都是事务开始的时候,一旦任意一步执行完毕因为系统宕机了。只写了两个中的任意一个。此时就会导致redo和binlog日志不一致的情况。
    • 并且即使执行了5,6步成功了,也不能保证redo和binlog日志是一样的。这就会导致了数据不一致的问题。而commit就是保证连个日志数据一致,事务才算提交成功

11.3.3流程小结(8步,非常重要)

  1. BufferPool查找数据
  2. 原来的数据写入undo log
  3. 修改BufferPool数据
  4. 写入redo log buffer
  5. 提交事务时,把redo log刷盘(prepare状态)
  6. 执行器会生成更新操作的 binlog,binlog 刷盘
  7. redo log(打上commit标记)
  8. 内存中脏数据刷入磁盘

11.4查询优化小结

1、查询的时候用什么字段查什么字段,

2、避免索引失效(如子查询、!=、like 以%开头,复合索引不在第一列索引、使用函数)

在这里插入图片描述

举报

相关推荐

0 条评论