MySQL update执行流程到 redo log深刻理解

前面咱们分析过一个查询语句的执行流程,而且解释了执行过程当中涉及的模块。一条查询语句通常是通过链接器、分析器、优化器、执行器等功能模块,最后到达存储引擎。老铁们能够点击连接 查询语句在 MySQL 如何执行 学习上篇内容。数据库

此次,咱们来深刻学习一条更新语句在 MySQL 中的执行流程。经过此文咱们能够充分了解 什么是 Redo Log缓存

表结构建立

首先咱们先建立一张表,只有主键 ID,以及 int 类型字段 c。架构

create table T(ID int primary key, c int);

如今咱们要更新一条数据,语句以下:学习

update T set c=c+1 where ID=2;

更新语句其实也跟查询语句的流程相似,只不过多了 redo log、undo log 以及 binlog 日志。优化

未命名文件.png

上一篇查询语句的执行流程咱们说过,在一个表上有更新的时候,跟这个表有关的查询缓存会失效,因此这条语句会把整个 T 表的缓存结果都清空。这也是为什么咱们不建议使用查询缓存的缘由。spa

帐本与记帐板

假如您当了小超市老板,天然会有一个帐本记录交易记录,可是可能还要一个赊帐记录。由于村里有个姑娘叫小芳,长得美丽又善良。有时候会到你这里白嫖,额,不是,是赊帐。你先把记录写在小粉板上,等夜深人静的时候就把粉板的数据同步到归档的帐本中。固然粉板也有满的时候,因此当粉板满了就要对帐写入帐本中,插件

因此,若是有人要来赊帐,或者还帐的时候,一般有两种作法:设计

  1. 直接把帐本翻出来,把此次的赊帐加上去或者扣除。
  2. 先在粉板上记下此次的账,等打烊后再把帐本翻出来核算。

在生意忙的时候,咱们确定选择后者,由于前者操做太麻烦了。首先,你得找到这我的的赊帐总额那条记录。你想一想,密密麻麻几十页,掌柜要找到那个名字,可 能还得带上老花镜慢慢找,找到以后再拿出算盘计算,最后再将结果写回到帐本上。这个时候小芳来赊帐,等半天。之后还怎么约小芳到小树林呢?3d

MySQL 中也有这个问题,若是每一次操做都要写进磁盘,而后磁盘也要找到对应的记录,而后再更新。整个过程的 IO 成本,查询成本都很高,为了解决这个问题,MySQL的设计者就用了相似小超市老板粉板的思路来提高更新效率。日志

而粉板和帐本配合的整个过程,其实就是 MySQL 里常常说到的 WAL 技术,WAL 的全称是Write-Ahead Logging,它的关键点就是先写日志,再写磁盘,也就是先写粉板,等不忙的时候再写帐本。

redo log

首先咱们要明确的是binlog 日志是在 server 层的,而redo logInnoDB 特有的。

当有一条记录须要更新的时候,InnoDB引擎就会先把记录写到 redo log(粉板)中,并更新内存,这个时候就算完成了。同时 引擎会在适当的时候将这个记录更新到磁盘里,而更新每每是系统比较闲的时候,这就是打样之后掌柜作的事情。

相似的,InnoDB 的 redo log 是固定大小的,好比能够配置为一组 4 个文件,每一个文件的大小是 1GB,那么这块“粉板”总共就能够记录 4GB 的操做。从头开始写,写到末尾就又回到开头循环写,以下面这个图所示。

redolog buff.png

write pos 是当前记录的位置,一边写一边后移,写到第 3 号文件末尾后就回到 0 号文件开头。checkpoint 是当前要擦除的位置,也是日后推移而且循环的,擦除记录前要把记录更新到数据文件。

write pos 和 checkpoint 之间的是“粉板”上还空着的部分,能够用来记录新的操做。若是 write pos 追上 checkpoint,表示“粉板”满了,这时候不能再执行新的更新,得停下来先擦掉一些记录,把 checkpoint 推动一下。

有了 redo log,InnoDB 就能够保证即便数据库发生异常重启,以前提交的记录都不会丢失,这个能力称为crash-safe

要理解 crash-safe 这个概念,能够想一想咱们前面赊帐记录的例子。只要赊帐记录记在了粉板上或写在了帐本上,以后即便掌柜忘记了,好比忽然停业几天,恢复生意后依然能够经过帐本和粉板上的数据明确赊帐帐目。

binlog

MySQL 的总体架构其实有两块:一块是 Server 层,还有一块是 引擎层,负责存储相关。前面咱们提到的 redo logInnoDB 引擎持有的,而 Server 层也有本身的日志,叫 binlog(归档日志)。

那为什么会有两份日志呢?

由于最开始 MySQL 里并无 InnoDB 引擎。MySQL 自带的引擎是 MyISAM,可是 MyISAM 没有 crash-safe 的能力(由于是 Server 层与引擎层是两个独立的模块),binlog 日志只能用于归档。而 InnoDB 是另外一个公司以插件形式引入 MySQL 的,既然只依靠 binlog 是没有 crash-safe 能力的,因此 InnoDB 使用另一套日志系统——也就是 redo log 来实现 crash-safe 能力。

假如只有 binlog,当 Server 层 binlog 日志写完后 引擎层尚未同步到磁盘就断电了。这个时候重启后 binlog 记录了更新操做,可是引擎层并无写入磁盘中就致使了从库使用该 binlog 同步数据不一致。

redo log、 binlog 的 差别

  1. redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,全部引擎均可以使用。
  2. redo log 是物理日志,记录的是“在某个数据页上作了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,好比“给 ID=2 这一行的 c 字段加 1 ”。
  3. redo log 是循环写的,空间固定会用完;binlog 是能够追加写入的。“追加写”是指 binlog 文件写到必定大小后会切换到下一个,并不会覆盖之前的日志。

Update 语句执行流程

有了对两个日志的概念理解,咱们就能够继续理解执行器与 InnoDB 引擎执行 update 语句时的内部流程。

  1. Server 层的执行器先调用引擎取出 ID=2 这一行。ID 是主键,引擎直接用树搜索找到这一行。若是 ID=2 这一行所在的数据页原本就在内存中,就直接返回给执行器;不然,须要先从磁盘读入内存,而后再返回。
  2. 执行器拿到数据把这个值 + 1,获得新一行的数据,再调用存储引擎接口写入这行新数据。
  3. InnoDB 引擎将这行数据更新到内存中,同时将这个更新操做所影响的页日志记录到 redo log 中,此时日志处于 prepare 状态,而后会告知 执行器完成了,随时能够提交事务。
  4. 执行器生成这个操做的 binlog ,并把 binlog 写入磁盘。
  5. 执行器继续调用引擎的的提交事务接口,引擎收到请求就把刚刚写入的 redo log 的状态改为提交(commit),更新完成。

最后三步看上去有点“绕”,将 redo log 的写入拆成了两个步骤: prepare 和 commit,这就是"两阶段提交"。

以下图所示,绿色表明执行器执行,白色表明 InnoDB 引擎执行:

update流程.png

update流程

两阶段提交

为何必须有“两阶段提交”呢?这是为了让两份日志之间的逻辑一致。要说明这个问题,咱们得从文章开头的那个问题提及:怎样让数据库恢复到半个月内任意一秒的状态?

前面咱们说过了,binlog 会记录全部的逻辑操做,而且是采用“追加写”的形式。若是你的 DBA 承诺说半个月内能够恢复,那么备份系统中必定会保存最近半个月的全部 binlog,同时系统会按期作整库备份。这里的“按期”取决于系统的重要性,能够是一天一备,也能够是一周一备。

当须要恢复到指定的某一秒时,好比某天下午两点发现中午十二点有一次误删表,须要找回数据,那你能够这么作:

  1. 首先,找到最近的一次全量备份,若是你运气好,可能就是昨天晚上的一个备份,从这个备份恢复到临时库;
  2. 而后,从备份的时间点开始,将备份的 binlog 依次取出来,重放到中午误删表以前的那个时刻。

因为 redo log 和 binlog 是两个独立的逻辑,若是不用两阶段提交,要么就是先写完 redo log 再写 binlog,或者采用反过来的顺序。咱们看看这两种方式会有什么问题。(会形成数据不一致)

仍然用前面的 update 语句来作例子。假设当前 ID=2 的行,字段 c 的值是 0,再假设执行 update 语句过程当中在写完第一个日志后,第二个日志尚未写完期间发生了 crash,会出现什么状况呢?

先写 redo log 后写 binlog

假如在引擎 写完 redo log 后,bin log 没有写完,异常重启,依然能够根据 redo log 日志把数据恢复,可是 binlog 没有记录这个语句。 因此从库 经过 binlog 同步数据就致使没有把这个这行数据同步过来,丢失了这个事务操做形成数据不一致。

先写 binlog 再写 redo log

若是写完 binlog 后 崩溃,因为 redo log 尚未写,崩溃恢复后这个事务无效,可是 binlog 却有记录。从库根据 这个 binlog 日志就会致使多处一个事务,与主库不一致。

简单说,redo log 和 binlog 均可以用于表示事务的提交状态,而两阶段提交就是让这两个状态保持逻辑上的一致。(敲黑板了同窗们)
关注公众号 JavaStorm 解锁更多精彩
二维码.jpg

相关文章
相关标签/搜索