Mysql中的事务日志——redo日志

本文主要讲解了Mysql的InnoDB引擎的事务的基础知识,以及redo日志的结构与实现,日志的特点,。本文参考资料见文末

事务的实现

事务的隔离性由是数据库中的锁来实现,原子性,隔离性,持久性由redo log 和 undo log 来实现(其中redo日志来实现事务的持久性), redo log 和 undo log 都是一种恢复操作

redo 恢复提交事务修改的页操作,而undo 回滚行记录到某个特定版本。

redo 通常是物理日志,记录的是页的物理修改操作,undo是逻辑日志,根据每行进行记录。

redo 日志

日志的两个部分

​ 这个日志有两部分组成,一部分是内存中的重做日志缓冲(redo log buffer)其是易失的,第二部分是重做日志文档(redo log file)其是持久的

Force Log at Commit(日志写入日志文档)

​ InnoDB引擎是事务的存储引擎,其通过Force Log at Commit 机制来实现事务的持久性——当事务提交的时候,必须将该事务的所有日志写入重做日志文档进行持久化,待事务的COMMIT操作完成才算完成

两个日志的特点(不需要读取操作,随机读写)

其中,重做日志包括了两部分(redo和undo两部分) ,redo log 来保证事务的持久性,undo log 来帮助事务回滚和MVCC的功能。

  • redo是顺序写的,在数据库的运行时不需要对redo log 的文档进行读取操作
  • 而 undo log是需要进行随机读写的(因为说不定需要回滚)

确保日志写入日志文档

​ 当没有使用O_DIRECT的选项时,数据库会进行下图的做法(O_DIRECT选项是在Linux系统中的选项,使用该选项后,对文档进行直接IO操作,不经过文档系统缓存,直接写入磁盘

提高数据库的性能

​ 我们知道写入磁盘的fsync操作十分耗费时间, 那么为了提高性能,我们可以选择当事务提交的时候,日志不写入重做日志文档,而是等待一个时间周期后在执行fsync的操作,并非强制在事务提交前进行一次fsync操作。

​ 缺点:当数据库宕机的时候,由于部分日志没有刷新到磁盘,会丢失最后一段时间的事务。

​ 但是需要记住的是,这种方法失去了事务的ACID的特性在插入大批量的数据时,应该在插入完之后,进行一次commit操作,而不是插入一条后进行一次commit操作,这样做能够使事务方法在回滚的时候回滚到事务最开始的状态。

重做日志的存储与结构

​ 重做日志是建立引擎上的,对于InnoDB引擎来说,重做日志都是以512字节进行存储的。这意味着重做日志缓存,重做日志文档都是以 “块” 的方式来保存,叫做 “重做日志块” (磁盘扇区大小都是512字节)。

​ 若一个页中产生的重做日志块数量大于 512 字节,那么需要分割多个重做日志块进行存储。因为都是512字节,所以重做日志块的写入可以保证原子性,不需要doublewrite技术。

​ 下面来看一下:重做日志缓存的结构!

​ 接着重点讲一下,FIRST_REC_GROUP 的意思

重做日志组(重做日志文档的组合)

​ log group 为重做日志组,其中与许多重做日志文档,InnoDB 实际只有一个log group(源码支持多个,但是在配置文档中禁止了)

它是一个逻辑上的概念,实际上没有一个存储的物理文档来表示log group信息。

它由许多个重做日志文档组成,每个日志文档的大小都是相同的。在 InnoDB 的 1.2版本之前,重做日志文档的总大小小于 4GB,之后提高为512 GB .

​ 重做日志文档存储的就是log buffer中保存的 log block,也是按照块的方式去存储。

log buffer 的提交

  • 当事务提交的时候

  • 当log buffer 中有一般的内存空间已经被使用时

  • log checkpoint时

    存在以上三种情况的时候,内存中的log block会刷新到磁盘上

LSN (Log Sequence Number/日志序列号)

​ 在InnoDB引擎中,LSN占用8字节,并且单调递增。LSN表示的含义有:

  • 重做日志的写入的总量
  • checkPoint的位置
  • 页的版本

如果当前重做日志的LSN为1000,一个事务写入了100字节的重做日志,那么LSN变为1100,又有事务T2写入了200字节的重做日志,那么lsn就变成了1300

LSN不仅记录在重做日志中,还存在每个页中,在每个页的头部,有一个值为FIL_PAGE_LSN,记录了该页的LSN.

在该页中,LSN表示该页最后刷新时 LSN 的大小,因为重做日志记录的是每个页的日志,因此页中的LSN用来判断页是否需要进行恢复操作。

如:

​ 页P1的LSN为10000,那么数据库启动的时候,InnoDB检测到写入重做日志的LSN为13000,且事务已经提交。

​ 那么数据库需要进行恢复操作,将重做日志应用到P1页中。

如果重做日志的LSN小于P1页中的LSN,不需要重做,因为P1页中的LSN表示页已经被刷新了

通过命令 SHOW ENGINE INNODB STATUS来查看LSN的情况,log的部分会出现下面的参数

  • Log sequence number 表示当前的LSN(日志缓存当中)
  • Log flushed up to 表示刷新到重做日志文档的LSN
  • Last checkpoint at 表示刷新到磁盘的LSN

恢复

​ InnoDB存储引擎在启动的时候,无论上次数据库是否正常关闭,都会尝试进行恢复,checkPoint表示刷新到磁盘页的LSN,在恢复过程中,仅需恢复checkPoint开始的日志部分。

参考资料:

https://juejin.im/post/5c3c5c0451882525487c498d#heading-17

《Mysql技术内幕——InnoDB存储引擎》

原文:大专栏  Mysql中的事务日志——redo日志


猜你喜欢

转载自www.cnblogs.com/chinatrump/p/11423694.html