02 | 日志系统:一条SQL更新语句是如何执行的?
本节课的内容主要在于介绍redo log(重做日志)和binlog(归档日志)。更新数据的时候涉及这两个重要日志模块(这句来自课程笔记)。binlog属于上一节课提到的Server层,redo log则属于存储引擎层。由此也可看除出,binlog是逻辑日志,而redo log是物理日志。
Redo log
MySQL通过使用WAL技术(Write-Ahead Logging)提升更新效率,其关键在于先写日志,再写磁盘。课程中以粉板与账本举例:当有人赊账或是还账时,柜台需要记账。当业务繁忙时,均先记在粉板上,当不忙的时候,再写回账本。注:写日志的本质也是在写磁盘,只不过写日志时是顺序写,而写磁盘时是随机写,因此读写速度有差异。InnoDB中的redo log是固定大小的,可以想象循环队列的数据结构,一边是队头指针(write pos),一边是队尾指针(checkpoint)。队头指针是写的起始指针,队尾指针是擦除内容的起始指针。
redo log为MySQL提供了crash-free功能,即当数据库发生异常重启,之前提交的记录也都不会消失,依旧能够进行版本回退。
Binlog
binlog与redo log之间的区别,我直接摘抄了课程中的文字贴于下文。
1、redo log 是 InnoDB 引擎特有的;binlog 是 MySQL 的 Server 层实现的,所有引擎都可以使用。
2、redo log 是物理日志,记录的是“在某个数据页上做了什么修改”;binlog 是逻辑日志,记录的是这个语句的原始逻辑,比如“给 ID=2 这一行的 c 字段加 1 ”。
3、redo log 是循环写的,空间固定会用完;binlog 是可以追加写入的。“追加写”是指 binlog 文件写到一定大小后会切换到下一个,并不会覆盖以前的日志。
基于此,我们针对一条SQL更新语句的执行流程分析如下:
1、执行器找引擎请求返回符合条件的记录。若存在于内存中,则直接返回,否则将从磁盘中调入内存。
2、执行器获得记录后,对其进行相应的操作,并调用引擎接口写入新数据。
3、引擎将新数据进行更新,并将相应操作记录到redo log中,此时redo log的状态为prepare。
4、执行器再生成更新操作的binlog,并写入磁盘。
5、最后把redo log的状态改为commit,并进行提交。
两阶段提交
两阶段提交的目的主要保证这两个重要日志在逻辑上能够保证一致。在课程中提到了不用两阶段提交的情况下,如果出现第一个日志写完成后,第二个日志还未写完便发生异常的情况时,会导致逻辑日志与物理日志的记录无法正确对应,则数据库将无法恢复到异常前的状态。
该随笔主要作用是为在学习课程后,复习以加深印象,并为之后能快速复习重要知识点准备的。若记录不完全或理解不正确,欢迎讨论或移步正课学习。
以上!