天天看点

一条MySQL更新语句是如何执行的?

查询语句更新流程

更新流程前边和查询一样也要走一遍查询,因为更新之前必须拿到(查询)更新的数据,先上一张流程图,然后看详细阅读下面的各个步骤。

一条MySQL更新语句是如何执行的?

mysql执行流程图

执行流程:

1.「连接验证」

需要MySQL客户端登录,需要一个 连接器 来连接用户和MySQL数据库,“mysql -u 用户名 -p 密码” 进行MySQL登录,在完成 TCP握手 后,连接器会根据输入的用户名和密码验证登录身份。

MySQL服务端和客户端的通信方式采用的是「半双工协议」。通信的时候,数据可以双向传输,但是同一时间只能有一台服务器在发送数据。

2.「查询缓存」

mysql8之后就去掉了查询缓存,因为太鸡肋了。当数据表发生修改时,涉及到这个表的查询缓存都会失效。这可能导致过多的缓存失效,并引发不一致的数据查询结果。

可以用过sql查看查询缓存是否开启。

SHOW VARIABLES LIKE 'query_cache_type';
           

3.「分析器」

语法此法分析,在这里首先会把整个sql打碎,并且能够识别关键字和非关键字,根据sql语句生成一个数据结构,也叫做解析树。

4.「预处理」

检查表名和字段名等相关信息合法性。

5.「优化器」

根据解析树生成不同的执行计划,然后选取一中最优的执行计划,哪种执行计划开销小就选择哪种。

优化器可以做哪些事情:

  1. 查询重写:将复杂的查询语句转换为等效但更简单的形式,以减少计算和存储成本。
  2. 查询优化:考虑多种执行策略和连接方式,并估计每个选择的成本,以选择最优的执行计划。
  3. 索引选择
  4. 连接顺序优化
  5. 子查询优化

6.「执行器」

调用存储引擎的api执行sql,执行查询,并将结果返回。其中查询语句是查询Buffer Pool,如果Buffer Pool没有发出去缺页提醒,去磁盘查找并将数据页存储到Buffer Pool,最后将结果返回,以上就是查询的流程。

Update语句的执行流程

更新用到了日志和缓存,先来补充日志和缓存。

binlog

binlog用于记录数据库执行的写入操作不包括查询,用二进制形式保存在磁盘中。binlog是server层,也就是不管是什么存储引擎都会有。binlog是采用追加方式写入的,顺序写。

binlog主要的使用场景有主从复制和数据恢复。binlog数据恢复也可以被称为重放操作。因为在使用binlog文件进行数据恢复时,会重放在该文件中记录的所有操作以实现数据的回滚,从而达到恢复数据的目的。

redo log

mysql事务的四大特性之一持久性,只要事务提交就被永久保存下来,为了防止mysql拓机,Buffer Poll没来的及刷入磁盘,导致数据丢失,由于Innodb是以页为单位进行交互,如果一个事务只修改几个字节,那么刷新整个页面太浪费性能。如果一个事务是跨好多页修改,这些页面不连续使用随机IO写入性能太差。因此mysql设计了redo log,只是记录事务对数据也做了哪些修改,比如xx表空间中yy数据页zz偏移量做了xx更新,记录修改后的值,属于物理日志。

mysql每执行一条DML语句都先写入 redo log buffer,后续某个时间点在一次性将多个操作写入到 redo log file。先写日志再写磁盘,这种就是经常说的WAL(write-ahead logging)技术。有了 redo log,InnoDB 就可以保证即使数据库发生异常重启,之前提交的记录都不会丢失,这个能力称为crash-safe。

一条MySQL更新语句是如何执行的?

wal

mysql支持三种将redo log buffer分别是

  • 0(延时写):每秒写入OS Buffer并调用fsync写入磁盘,当系统崩溃会丢失1秒钟的数据
  • 1(实时写):每次提交都会写入OS Buffer并且调用fsync,这种不会丢失数据,性能差。
  • 2(实时写,延时刷):每次提交都会从写入os buffer,然后每秒调用fsync写入日志。
一条MySQL更新语句是如何执行的?

写入时机

redo log采用了大小固定,循环写入的方式。write pos 是当前记录的位置,一边写一边后移,checkpoint 是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件。write pos 和 checkpoint 之间的是还空着的部分,可以用来记录新的操作。如果 write pos 追上 checkpoint,这时候不能再执行新的更新,得停下来先擦掉一些记录,把 checkpoint 推进一下。

一条MySQL更新语句是如何执行的?

循环写入

「崩溃恢复和重启mysql,redo log都做了什么?」

在数据库重新启动后,崩溃恢复机制会开始执行,以恢复数据库的一致性和持久性。崩溃恢复过程首先会检查redo log中记录的事务修改操作。

  • 在数据库启动时,会记录当前的LSN值,表示崩溃之前已经写入redo log的位置。
  • 在崩溃恢复过程中,从redo log中读取日志记录,并检查其LSN值。

如果LSN小于当前LSN值,表示该日志记录是在崩溃之前写入redo log的操作,需要重新应用该日志记录中的修改操作。

如果LSN大于或等于当前LSN值,表示该日志记录是在崩溃之后写入redo log的操作,可以忽略或跳过该日志记录。

undo log

Undo log(回滚日志)是数据库管理系统中的一种机制,用于实现事务的回滚操作和数据的一致性维护。它记录了事务执行期间对数据库进行的修改操作,以便在需要回滚事务或进行崩溃恢复时能够撤销这些修改,将数据恢复到事务开始之前的状态。

1.「记录修改操作」:

在事务执行期间,如果对数据库中的数据进行了修改(例如插入、更新或删除操作),则将相应的修改操作记录到Undo log中。

Undo log记录了原始数据的逻辑操作,即如何撤销事务对数据的修改。

2.「撤销操作」:

当需要回滚事务时,数据库引擎会利用Undo log中的信息,按照相反的顺序执行记录的修改操作,将数据恢复到事务开始之前的状态。

3.「崩溃恢复」:

在数据库崩溃后重新启动时,可以使用Undo log来撤销未提交事务的修改,以保持数据库的一致性。

通过使用Undo log,数据库能够实现事务的回滚操作,保证数据的一致性,并在崩溃恢复过程中恢复数据库到崩溃前的状态。它是实现事务的隔离性和持久性的重要组成部分。

buffer poll

用于缓存数据库中的数据页。它起到了提高数据库性能的作用,通过将磁盘上的数据加载到内存中,减少磁盘访问的频率。

当需要读取数据时,数据库首先在Buffer Pool中查找相应的数据页,如果找到则直接返回数据,避免了磁盘IO操作。当需要写入数据时,数据库将数据先写入Buffer Pool中的数据页,然后由后台线程定期将修改的数据页刷新到磁盘。

更新执行的流程

更新流程一样也要走一遍查询,因为更新之前必须拿到(查询)更新的数据。

  1. 追加undo:顺序将旧值写入undo磁盘文件。
  2. 更新buffer pool:将buffer pool中数据更新。
  3. 写redo缓存:先将redo日志写入redo buffer。
  4. 追加redo:从redo buffer中拿到数据 顺序写redo磁盘文件。
  5. 追加binlog:顺序写binlog磁盘文件。
  6. 打标记:写入commit标记至redo磁盘文件中,代表本次update的事务已经commit了,且redo与binlog一致了。
  7. 刷盘:单独有线程会将buffer pool中数据刷至磁盘,以随机的方式。

「为什么要二阶段提交?」

两阶段提交(简称2PC)是为了保证分布式系统中的多个参与者在进行事务提交时的数据一致性而引入的协议。它确保了在事务提交过程中,所有参与者要么都提交事务,要么都回滚事务,从而保持数据的一致性。

  1. 准备阶段(Prepare Phase):协调者向所有参与者发送事务准备请求,参与者执行事务操作,并将结果反馈给协调者。如果所有参与者都准备好提交事务,协调者将发送提交请求;如果任何一个参与者未能准备好提交事务,协调者将发送回滚请求。
  2. 提交阶段(Commit Phase):协调者根据准备阶段的反馈结果,决定是发送提交请求还是回滚请求。如果所有参与者都准备好提交事务,协调者发送提交请求,参与者将正式提交事务并释放资源;如果任何一个参与者未能准备好提交事务,协调者发送回滚请求,参与者将回滚事务并释放资源。

如果没有使用两阶段提交协议,可能会导致数据不一致的问题,具体如下:

  1. 先写Redo Log,再写Binlog: 如果在写完Redo Log后发生MySQL宕机,而尚未写入Binlog,那么在重启后,Redo Log中存在事务记录,MySQL会认为这些事务已成功提交,但是由于Binlog缺失了相应的记录,导致Binlog与Redo Log的数据不一致。在以后使用Binlog进行数据恢复时,会出现数据丢失的情况。
  2. 先写Binlog,再写Redo Log: 如果在写完Binlog后发生MySQL宕机,而尚未写入Redo Log,那么在重启后,Redo Log中将没有相应的记录,MySQL会判断这些事务未成功提交,但是由于Binlog中存在这些记录,导致Binlog与Redo Log的数据不一致。在以后使用Binlog进行数据恢复时,会多出一个未提交的事务操作。

继续阅读