redo log(重做日志)
redo log是一种物理日志
redo log日志称为重做日志,提供再写入操作,恢复提交事务修改的页操作,用来保证事务的持久性。只需要把修改了哪些东西记录一下就好.比如某个事务将系统表空间中第10号页面中偏移量为100处的那个字节的值1改成2.我们只需要记录一下:将第0号表空间的10号页面的偏移量为100处的值更新为2.lnnoDB引擎的事务采用了WAL技术(Write -Ahead Logging),这种技术的思想就是先写日志,再写磁盘,只有日志写入成功,才算事务提交成功,这里的日志就是redo log。当发生宕机且数据来刷到磁盘的时候,可从通过redo log来恢复,保证ACID中的D,这就是redo log的作用。
组成部分
重做日志缓存(redo log buff):
重做日志的缓冲(redo log buffer),保存在内存中,是易失的。在服务器启动时就向操作系统申请了一大片称之为redo log buffer的连续内存空间,翻译成中文就是redo日志缓冲区。这片内存空间被划分成若干个连续的redo log block。一个redo log block占用512字节大小。
重做日志文件(redo log):
重做日志文件(redologfile),保存在硬盘中,是持久的。
redo log 是物理日志,记载着每次在某个页上做了什么修改。写redo log也是需要写磁盘的,但它的好处就是顺序IO(我们都知道顺序IO比随机IO快非常多),写入的速度很快。
写入机制
- 事务开始之后,就开始产生 redo log 日志了,在事务执行的过程中,redo log开始逐步落盘。
- 当对应事务的脏页写入到磁盘之后,redo log 的使命就完成了,它所占用的空间也就可以被覆盖了。
- InnoDB 的 redo log 是固定大小的,比如可以配置为一组 4 个文件,每个文件的大小是 1GB。从头开始写,写到末尾就又回到开头循环写
- write pos 是当前记录的位置,一边写一边后移,写到第 3 号文件末尾后就回到 0 号文件开头。
- checkpoint 是当前要擦除的位置,也是往后推移并且循环的,擦除记录前要把记录更新到数据文件。
- write pos 和 checkpoint 之间的的部分,可以用来记录新的操作。如果 write pos 追上 checkpoint,表示“粉板”满了,这时候不能再执行新的更新,得停下来先擦掉一些记录,把 checkpoint 推进一下。
show variables like '%innodb_log%'每个InnoDB存储引擎至少有1个重做日志文件组(group),每个文件组至少有2个重做日志文 件,默认为ib_logfile0和ib_logfile1。
工作流程:
- 第1步:先将原始数据从磁盘中读入内存中来,修改数据的内存拷贝
- 第⒉步:生成一条重做日志并写入redo log buffer ,记录的是数据被修改后的值
- 第3步:当事务commit时,将redo log buffer中的内容刷新到redolog file ,对redo log file采用追加写的方式
- 第4步:定期将内存中修改的数据刷新到磁盘中
刷盘策略
innodb_flush_log_at_trx_commit=1(默认)
- 设置为0:表示每次事务提交时不进行刷盘操作。(系统黙认master thread每隔1s进行一次重做日志的同步)
- 设置为1:表示每次事务提交时都将进行同步,刷盘操作
- 设置为2:表示每次事务提交时都只把 redo log buffer内容写入page cache,不进行同步。由os自己决定什么时候同步到磁盘文件。
另外,
InnoDB
存储引擎有一个后台线程,每隔1 秒,就会把 redo log buffer 中的内容写到文件系统缓存(
page cache
),然后调用 fsync刷盘。
也就是说,一个没有提交事务的 redo log 记录,也可能会刷盘。
undo log(回滚日志)
undo log是一种逻辑日志
undo log是mysql中比较重要的事务日志之一,顾名思义,undo log是一种用于撤销回退的日志,在事务没提交之前,MySQL会先记录更新前的数据到 undo log日志文件里面,当事务回滚时或者数据库崩溃时,可以利用 undo log来进行回退。
作用
- 提供事务回滚操作(undo log实现事务的原子性)
- 提供多版本控制(MVCC)undo log实现多版本并发控制
存储机制
undo log的存储由InnoDB存储引擎实现,数据保存在InnoDB的数据文件中。在InnoDB存储引擎中,undo log是采用分段(segment)的方式进行存储的。rollback segment称为回滚段,每个回滚段中有1024个undo log segment。在MySQL5.5之前,只支持1个rollback segment,也就是只能记录1024个undo操作。在MySQL5.5之后,可以支持128个rollback segment,分别从resg slot0 - resg slot127,每一个resg slot,也就是每一个回滚段,内部由1024个undo segment 组成,即总共可以记录128 * 1024个undo操作。
如上图,可以看到,undo log日志里面不仅存放着数据更新前的记录,还记录着RowID、事务ID、回滚指针。其中事务ID每次递增,回滚指针第一次如果是insert语句的话,回滚指针为NULL,第二次update之后的undo log的回滚指针就会指向刚刚那一条undo log日志,依次类推,就会形成一条undo log的回滚链,方便找到该条记录的历史版本。