02 SQL更新语句执行流程

02 SQL更新语句执行流程

与查询流程不一样的是,更新流程还涉及两个重要的日志模块。

​ redo log(重做日志)和 binlog(归档日志)

redo log 物理日志 binlog 逻辑日志

redo log

WAL 的全称是 Write-Ahead Logging。

关键点就是先写日志,再写磁盘,用来提升更新效率。

具体来说,当有一条记录需要更新的时候,InnoDB 引擎就会先把记录写到 redo log 里面,并更新内存,这个时候更新就算完成了。同时,InnoDB 引擎会在适当的时候,将这个操作记录更新到磁盘里面,而这个更新往往是在系统比较空闲的时候做。

InnoDB 的 redo log 是固定大小的,比如可以配置为一组 4 个文件,每个文件的大小是 1GB,那么这块“粉板”总共就可以记录 4GB 的操作。从头开始写,写到末尾就又回到开头循环写,并覆盖之前的记录。

write pos是当前记录的位置,check point 是当前要擦除的位置。

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


binlog

redo log 是 InnoDB 引擎特有的日志Server 层也有自己的日志,称为 binlog(归档日志)

redo log 和binlog的区别:

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

将 redo log 的写入拆成了两个步骤:prepare 和 commit,这就是"两阶段提交"

图中浅色框表示是在 InnoDB 内部执行的,深色框表示是在执行器中执行的。

两阶段提交使得两份日志之间的逻辑一致。

具体原因

  1. 先写 redo log 后写 binlog。假设在 redo log 写完,binlog 还没有写完的时候,MySQL 进程异常重启。redo log 写完之后,系统即使崩溃,仍然能够把数据恢复回来,所以恢复后这一行 c 的值是 1。但是由于 binlog 没写完就 crash 了,这时候 binlog 里面就没有记录这个语句。因此,之后备份日志的时候,存起来的 binlog 里面就没有这条语句。

    如果需要用这个 binlog 来恢复临时库的话,由于这个语句的 binlog 丢失,这个临时库就会少了这一次更新,恢复出来的这一行 c 的值就是 0,与原库的值不同。

  2. 先写 binlog 后写 redo log。如果在 binlog 写完之后 crash,由于 redo log 还没写,崩溃恢复以后这个事务无效,所以这一行 c 的值是 0。但是 binlog 里面已经记录了“把 c 从 0 改成 1”这个日志。所以,在之后用 binlog 来恢复的时候就多了一个事务出来,恢复出来的这一行 c 的值就是 1,与原库的值不同。

如果不使用“两阶段提交”,那么 数据库的状态 就有可能和 用它的日志恢复出来的库 的状态不一致。


问:在什么场景下,一天一备会比一周一备更有优势呢?或者说,它影响了这个数据库系统的哪个指标?

答:一天一备的最长恢复时间更短,当然这个是有成本的,因为更频繁全量备份需要消耗更多存储空间,所以这个 RTO 是成本换来的,就需要你根据业务重要性来评估了。(用空间换取时间)。

posted @ 2024-02-19 15:39  zhyan0502  阅读(45)  评论(0编辑  收藏  举报