在事务的实现机制上,MySQL采用的是WAL(Write-ahead logging,预写式日志)机制来实现的。

在使用WAL的系统中,所有的修改都先被写入到日志中,然后再被应用到系统中。通常包含redo和undo两部分信息。

为什么需要使用WAL,然后包含redo和undo信息呢?举个例子,如果一个系统直接将变更应用到系统状态中,那么在机器掉电重启之后系统需要知道操作是成功了,还是只有部分成功或者是失败了(为了恢复状态)。如果使用了WAL,那么在重启之后系统可以通过比较日志和系统状态来决定是继续完成操作还是撤销操作。

redo log称为重做日志,每当有操作时,在数据变更之前将操作写入redo log,这样当发生掉电之类的情况时系统可以在重启后继续操作。

undo log称为撤销日志,当一些变更执行到一半无法完成时,可以根据撤销日志恢复到变更之间的状态(回滚)。

MySQL中用redo log来在系统Crash重启之类的情况时修复数据(事务的持久性),而undo log来保证事务的原子性。

InnoDB存储引擎是以页为单位来管理存储空间的,我们进行的增删改查操作其实本质上都是在访问页面(包括读页面、写页面、创建新页面等操作)。在真正访问页面之前,需要把在磁盘上的页缓存到内存中的Buffer Pool之后才可以访问。但是在事务的时候又强调过一个称之为持久性的特性,就是说对于一个已经提交的事务,在事务提交后即使系统发生了崩溃,这个事务对数据库中所做的更改也不能丢失。

如果我们只在内存的Buffer Pool中修改了页面,假设在事务提交后突然发生了某个故障,导致内存中的数据都失效了,那么这个已经提交了的事务对数据库中所做的更改也就跟着丢失了,这是我们所不能忍受的。那么如何保证这个持久性呢?一个很简单的做法就是在事务提交完成之前把该事务所修改的所有页面都刷新到磁盘,但是这个简单粗暴的做法有些问题:

  • 刷新一个完整的数据页太浪费了:
    有时候我们仅仅修改了某个页面中的一个字节,但是我们知道在InnoDB中是以页为单位来进行磁盘IO的,也就是说我们在该事务提交时不得不将一个完整的页面从内存中刷新到磁盘,我们又知道一个页面默认是16KB大小,只修改一个字节就要刷新16KB的数据到磁盘上显然是太浪费了。

  • 随机IO刷起来比较慢
    :一个事务可能包含很多语句,即使是一条语句也可能修改许多页面,该事务修改的这些页面可能并不相邻,这就意味着在将某个事务修改的Buffer Pool中的页面刷新到磁盘时,需要进行很多的随机IO,随机IO比顺序IO要慢,尤其对于传统的机械硬盘来说。

怎么办呢?我们只是想让已经提交了的事务对数据库中数据所做的修改永久生效,即使后来系统崩溃,在重启后也能把这种修改恢复出来。所以我们其实没有必要在每次事务提交时就把该事务在内存中修改过的全部页面刷新到磁盘,只需要把修改了哪些东西记录一下就好,比方说某个事务将系统表空间中的第100号页面中偏移量为1000处的那个字节的值1改成2我们只需要记录一下:
将第0号表空间的100号页面的偏移量为1000处的值更新为2。

这样我们在事务提交时,把上述内容刷新到磁盘中,即使之后系统崩溃了,重启之后只要按照上述内容所记录的步骤重新更新一下数据页,那么该事务对数据库中所做的修改又可以被恢复出来,也就意味着满足持久性的要求。因为在系统崩溃重启时需要按照上述内容所记录的步骤重新更新数据页,所以上述内容也被称之为重做日志,也可以称之为redo 日志。与在事务提交时将所有修改过的内存中的页面刷新到磁盘中相比,只将该事务执行过程中产生的redo日志刷新到磁盘的好处如下:

1、redo日志占用的空间非常小
:存储表空间ID、页号、偏移量以及需要更新的值所需的存储空间是很小的。

2、redo日志是顺序写入磁盘的
:在执行事务的过程中,每执行一条语句,就可能产生若干条redo日志,这
些日志是按照产生的顺序写入磁盘的,也就是使用顺序IO。

redo日志格式

通过上边的内容我们知道,redo日志本质上只是记录了一下事务对数据库做了哪些修改。InnoDB针对事务对数据库的不同修改场景定义了多种类型的redo日志,但是绝大部分类型的redo日志都有下边这种通用的结构:

各个部分的详细释义如下:

字段名 说明
type 该条redo日志的类型,redo日志设计大约有53种不同的类型日志
space ID 表空间ID
page number 页号
data 该条redo日志的具体内容

简单的redo日志类型

我们用一个简单的例子来说明最基本的redo日志类型。我们前边介绍InnoDB的记录行格式的时候说过,如果我们没有为某个表显式的定义主键,并且表中也没有定义Unique键,那么InnoDB会自动的为表添加一个称之为row_id的隐藏列作为主键。为这个row_id隐藏列赋值的方式如下:

  • 服务器会在内存中维护一个全局变量,每当向某个包含隐藏的row_id列的表中插入一条记录时,就会把该变量的值当作新记录的row_id列的值,并且把该变量自增1。

  • 每当这个变量的值为256的倍数时,就会将该变量的值刷新到系统表空间的页号为7的页面中一个称之为Max Row ID的属性处。

  • 当系统启动时,会将上边提到的Max Row ID属性加载到内存中,将该值加上256之后赋值给我们前边提到的全局变量。

这个Max Row ID属性占用的存储空间是8 个字节,当某个事务向某个包含row_id 隐藏列的表插入一条记录,并且为该记录分配的row_id值为256的倍数时,就会向系统表空间页号为7的页面的相应偏移量处写入8个字节的值。但是我们要知道,这个写入实际上是在Buffer Pool中完成的,我们需要为这个页面的修改记录一条redo日志,以便在系统崩溃后能将已经提交的该事务对该页面所做的修改恢复出来。这种情况下对页面的修改是极其简单的,redo日志中只需要记录一下在某个页面的某个偏移量处修改了几个字节的值,具体被修改的内容是啥就好了,InnoDB把这种极其简单的redo日志称之为物理日志,并且根据在页面中写入数据的多少划分了几种不同的redo日志类型:

  • MLOG_1BYTE(type 字段对应的十进制数字为1):表示在页面的某个偏移量处写入1个字节的redo日志类型。

  • MLOG_2BYTE(type 字段对应的十进制数字为2):表示在页面的某个偏移量处写入2个字节的redo日志类型。

  • MLOG_4BYTE(type 字段对应的十进制数字为4):表示在页面的某个偏移量处写入4个字节的redo日志类型。

  • MLOG_8BYTE(type 字段对应的十进制数字为8):表示在页面的某个偏移量处写入8个字节的redo日志类型。

  • MLOG_WRITE_STRING(type 字段对应的十进制数字为30):表示在页面的某个偏移量处写入一串数据。

我们上边提到的Max Row ID属性实际占用8个字节的存储空间,所以在修改页面中的该属性时,会记录一条类型为MLOG_8BYTE的redo日志,MLOG_8BYTE的redo日志结构如下所示:

offset代表在页面中的偏移量。其余MLOG_1BYTE、MLOG_2BYTE、MLOG_4BYTE类型的redo日志结构和MLOG_8BYTE 的类似,只不过具体数据中包含对应个字节的数据罢了。MLOG_WRITE_STRING类型的redo日志表示写入一串数据,但是因为不能确定写入的具体数据占用多少字节,所以需要在日志结构中还会多一个len字段。

复杂一些的redo日志类型

有时候执行一条语句会修改非常多的页面,包括系统数据页面和用户数据页面(用户数据指的就是聚簇索引和二级索引对应的B+树)。以一条INSERT 语句为例,它除了要向B+树的页面中插入数据,也可能更新系统数据Max Row ID的值,不过对于我们用户来说,平时更关心的是语句对B+树所做更新:表中包含多少个索引,一条INSERT语句就可能更新多少棵B+树。

针对某一棵B+树来说,既可能更新叶子节点页面,也可能更新非叶子节点页面,也可能创建新的页面(在该记录插入的叶子节点的剩余空间比较少,不足以存放该记录时,会进行页面的分裂,在非叶子节点页面中添加目录项记录)。

在语句执行过程中,INSERT语句对所有页面的修改都得保存到redo日志中去。实现起来是非常麻烦的,比方说将记录插入到聚簇索引中时,如果定位到的叶子节点的剩余空间足够存储该记录时,那么只更新该叶子节点页面就好,那么只记录一条MLOG_WRITE_STRING 类型的redo日志,表明在页面的某个偏移量处增加了哪些数据就好了么?

别忘了一个数据页中除了存储实际的记录之后,还有什么File Header、PageHeader、Page Directory等等部分,所以每往叶子节点代表的数据页里插入一条记录时,还有其他很多地方会跟着更新,比如说:可能更新Page Directory中的槽信息、Page Header中的各种页面统计信息,比如槽数量可能会更改,还未使用的空间最小地址可能会更改,本页面中的记录数量可能会更改,各种信息都可能会被修改,同时数据页里的记录是按照索引列从小到大的顺序组成一个单向链表的,每插入一条记录,还需要更新上一条记录的记录头信息中的next_record属性来维护这个单向链表。

画一个简易的示意图就像是这样:

其实说到底,把一条记录插入到一个页面时需要更改的地方非常多。这时我们如果使用上边介绍的简单的物理redo 日志来记录这些修改时,可以有两种解决方案:

方案一:在每个修改的地方都记录一条redo 日志。
也就是如上图所示,有多少个加粗的块,就写多少条物理redo 日志。这样子记录redo日志的缺点是显而易见的,因为被修改的地方是在太多了,可能记录的redo 日志占用的空间都比整个页面占用的空间都多了。

方案二:将整个页面的第一个被修改的字节到最后一个修改的字节之间所有的数据当成是一条物理redo 日志中的具体数据。从图中也可以看出来,第一个被修改的字节到最后一个修改的字节之间仍然有许多没有修改过的数据,我们把这些没有修改的数据也加入到redo日志中去依然很浪费。

正因为上述两种使用物理redo日志的方式来记录某个页面中做了哪些修改比较浪费,InnoDB中就有非常多的redo日志类型来做记录。这些类型的redo日志既包含物理层面的意思,也包含逻辑层面的意思,具体指:

  • 物理层面看,这些日志都指明了对哪个表空间的哪个页进行了修改。

  • 逻辑层面看,在系统崩溃重启时,并不能直接根据这些日志里的记载,将页面内的某个偏移量处恢复成某个数据,而是需要调用一些事先准备好的函数,执行完这些函数后才可以将页面恢复成系统崩溃前的样子。

简单来说,一个redo日志类型而只是把在本页面中变动(比如插入、修改)一条记录所有必备的要素记了下来,之后系统崩溃重启时,服务器会调用相关向某个页面变动(比如插入、修改)一条记录的那个函数,而redo日志中的那些数据就可以被当成是调用这个函数所需的参数,在调用完该函数后,页面中的相关值也就都被恢复到系统崩溃前的样子了。这就是所谓的逻辑日志的意思。

当然,如果不是为了写一个解析redo日志的工具或者自己开发一套redo日志系统的话,那就不需要去研究InnoDB中的redo日志具体格式。

大家只要记住:redo日志会把事务在执行过程中对数据库所做的所有修改都记录下来,在之后系统崩溃重启后可以把事务所做的任何修改都恢复出来。

以组的形式写入redo日志

语句在执行过程中可能修改若干个页面。比如我们前边说的一条INSERT语句可能修改系统表空间页号为7的页面的Max Row ID属性(当然也可能更新别的系统页面,只不过我们没有都列举出来而已),还会更新聚簇索引和二级索引对应B+树中的页面。由于对这些页面的更改都发生在Buffer Pool中,所以在修改完页面之后,需要记录一下相应的redo日志。

在这个执行语句的过程中产生的redo日志被InnoDB人为的划分成了若干个不可分割的组,比如:

1、更新Max Row ID属性时产生的redo日志是不可分割的。

2、向聚簇索引对应B+树的页面中插入一条记录时产生的redo日志是不可分割的。

3、向某个二级索引对应B+树的页面中插入一条记录时产生的redo 日志是不可分割的。

4、还有其他的一些对页面的访问操作时产生的redo 日志是不可分割的….。

怎么理解这个不可分割的意思呢?我们以向某个索引对应的B+树插入一条记录为例,在向B+树中插入这条记录之前,需要先定位到这条记录应该被插入到哪个叶子节点代表的数据页中,定位到具体的数据页之后,有两种可能的情况:

情况一:该数据页的剩余的空闲空间充足,足够容纳这一条待插入记录,那么事情很简单,直接把记录插入到这个数据页中,记录一条redo日志就好了,我们把这种情况称之为乐观插入。

情况二:该数据页剩余的空闲空间不足,那么事情就很麻烦了,遇到这种情况要进行所谓的页分裂操作:

1、新建一个叶子节点;

2、然后把原先数据页中的一部分记录复制到这个新的数据页中;

3、然后再把记录插入进去,把这个叶子节点插入到叶子节点链表中;

4、非叶子节点中添加一条目录项记录指向这个新创建的页面;

5、非叶子节点空间不足,继续分裂。

很显然,这个过程要对多个页面进行修改,也就意味着会产生很多条redo日志,我们把这种情况称之为悲观插入。

另外,这个过程中,由于需要新申请数据页,还需要改动一些系统页面,比方说要修改各种段、区的统计信息信息,各种链表的统计信息,也会产redo日志。

当然在乐观插入时也可能产生多条redo日志。InnoDB认为向某个索引对应的B+树中插入一条记录的这个过程必须是原子的,不能说插了一半之后就停止了。比方说在悲观插入过程中,新的页面已经分配好了,数据也复制过去了,新的记录也插入到页面中了,可是没有向非叶子节点中插入一条目录项记录,这个插入过程就是不完整的,这样会形成一棵不正确的B+树。

我们知道redo日志是为了在系统崩溃重启时恢复崩溃前的状态,如果在悲观插入的过程中只记录了一部分redo日志,那么在系统崩溃重启时会将索引对应的B+树恢复成一种不正确的状态。

所以规定在执行这些需要保证原子性的操作时必须以组的形式来记录的redo日志,在进行系统崩溃重启恢复时,针对某个组中的redo日志,要么把全部的日志都恢复掉,要么一条也不恢复。在实现上,根据多个redo日志的不同,使用了特殊的redo日志类型作为组的结尾,来表示一组完整的redo 日志。

Mini-Transaction的概念

MySQL把对底层页面中的一次原子访问的过程称之为一个Mini-Transaction,比如上边所说的修改一次Max Row ID的值算是一个Mini-Transaction,向某个索引对应的B+树中插入一条记录的过程也算是一个Mini-Transaction。

一个所谓的Mini-Transaction可以包含一组redo日志,在进行崩溃恢复时这一组redo日志作为一个不可分割的整体。

一个事务可以包含若干条语句,每一条语句其实是由若干个Mini-Transaction组成,每一个Mini-Transaction又可以包含若干条redo日志,最终形成了一个树形结构。

redo日志的写入过程

redo log block和日志缓冲区

InnoDB为了更好的进行系统崩溃恢复,把通过Mini-Transaction生成的redo日志都放在了大小为512 字节的块(block)中。

我们前边说过,为了解决磁盘速度过慢的问题而引入了Buffer Pool。同理,写入redo日志时也不能直接直接写到磁盘上,实际上在服务器启动时就向操作系统申请了一大片称之为redo log buffer的连续内存空间,翻译成中文就是redo日志缓冲区,我们也可以简称为log buffer。这片内存空间被划分成若干个连续的redo log block,我们可以通过启动参数innodb_log_buffer_size来指定log buffer的大小,该启动参数的默认值为16MB。


mysql> show variables like 'innodb_log_buffer_size';
+------------------------+----------+
| Variable_name          | Value    |
+------------------------+----------+
| innodb_log_buffer_size | 16777216 |
+------------------------+----------+
1 row in set (0.03 sec)

向log buffer中写入redo日志的过程是顺序的,也就是先往前边的block中写,当该block的空闲空间用完之后再往下一个block中写。

我们前边说过一个Mini-Transaction执行过程中可能产生若干条redo日志,这些redo日志是一个不可分割的组,所以其实并不是每生成一条redo日志,就将其插入到log buffer中,而是每个Mini-Transaction运行过程中产生的日志先暂时存到一个地方,当该Mini-Transaction结束的时候,将过程中产生的一组redo日志再全部复制到log buffer中。

redo日志刷盘时机

我们前边说Mini-Transaction运行过程中产生的一组redo日志在Mini-Transaction结束时会被复制到log buffer 中,可是这些日志总在内存里呆着也不是个办法,在一些情况下它们会被刷新到磁盘里,比如:

1、log buffer 空间不足时,log buffer 的大小是有限的(通过系统变量innodb_log_buffer_size指定),如果不停的往这个有限大小的log buffer里塞入日志,很快它就会被填满。InnoDB认为如果当前写入log buffer 的redo日志量已经占满了log buffer总容量的大约一半左右,就需要把这些日志刷新到磁盘上。

2、事务提交时,我们前边说过之所以使用redo日志主要是因为它占用的空间少,还是顺序写,在事务提交时可以不把修改过的Buffer Pool页面刷新到磁盘,但是为了保证持久性,必须要把修改这些页面对应的redo日志刷新到磁盘。

3、后台有一个线程,大约每秒都会刷新一次log buffer中的redo日志到磁盘。

4、正常关闭服务器时等等。

redo日志文件组

MySQL的数据目录下默认有两个名为ib_logfile0和ib_logfile1的文件,log buffer中的日志默认情况下就是刷新到这两个磁盘文件中。如果我们对默认的redo日志文件不满意,可以通过下边几个启动参数来调节:

  • innodb_log_group_home_dir:指定了redo日志文件所在的目录,默认值就是当前的数据目录。

  • innodb_log_file_size:该参数指定了每个redo日志文件的大小,默认值为48MB,

  • innodb_log_files_in_group:该参数指定redo日志文件的个数,默认值为2,最大值为100。

所以磁盘上的redo日志文件可以不只一个,而是以一个日志文件组的形式出现的。这些文件以ib_logfile[数字](数字可以是0、1、2…)的形式进行命名。在将redo日志写入日志文件组时,是从ib_logfile0开始写,如果ib_logfile0写满了,就接着ib_logfile1写,同理,ib_logfile1写满了就去写ib_logfile2,依此类推。

如果写到最后一个文件该咋办?那就重新转到ib_logfile0继续写。

redo日志文件格式

log buffer本质上是一片连续的内存空间,被划分成了若干个512 字节大小的block。将log buffer中的redo日志刷新到磁盘的本质就是把block的镜像写入日志文件中,所以redo日志文件其实也是由若干个512字节大小的block组成。

redo日志文件组中的每个文件大小都一样,格式也一样,都是由两部分组成:前2048个字节,也就是前4 个block是用来存储一些管理信息的。从第2048 字节往后是用来存储log buffer中的block镜像的。

Log Sequence Number

自系统开始运行,就不断的在修改页面,也就意味着会不断的生成redo日志。redo日志的量在不断的递增,就像人的年龄一样,自打出生起就不断递增,永远不可能缩减了。

InnoDB为记录已经写入的redo日志量,设计了一个称之为Log SequenceNumber的全局变量,翻译过来就是:日志序列号,简称LSN。规定初始的lsn值为8704(也就是一条redo日志也没写入时,LSN的值为8704)。

我们知道在向log buffer中写入redo日志时不是一条一条写入的,而是以一个Mini-Transaction生成的一组redo 日志为单位进行写入的。从上边的描述中可以看出来,每一组由Mini-Transaction生成的redo日志都有一个唯一的LSN值与其对应,LSN值越小,说明redo日志产生的越早。

flushed_to_disk_lsn

redo日志是首先写到log buffer中,之后才会被刷新到磁盘上的redo日志文件。InnoDB中有一个称之为buf_next_to_write的全局变量,标记当前log buffer中已经有哪些日志被刷新到磁盘中了。

我们前边说lsn是表示当前系统中写入的redo日志量,这包括了写到logbuffer而没有刷新到磁盘的日志,相应的,InnoDB也有一个表示刷新到磁盘中的redo日志量的全局变量,称之为flushed_to_disk_lsn。系统第一次启动时,该变量的值和初始的lsn 值是相同的,都是8704。随着系统的运行,redo日志被不断写入log buffer,但是并不会立即刷新到磁盘,lsn的值就和flushed_to_disk_lsn的值拉开了差距。我们演示一下:

系统第一次启动后,向log buffer中写入了mtr_1、mtr_2、mtr_3这三个mtr产生的redo 日志,假设这三个mtr 开始和结束时对应的lsn值分别是:

mtr_1:8716 ~ 8916

mtr_2:8916 ~ 9948

mtr_3:9948 ~ 10000

此时的lsn已经增长到了10000,但是由于没有刷新操作,所以此时flushed_to_disk_lsn的值仍为8704。

随后进行将log buffer中的block刷新到redo日志文件的操作,假设将mtr_1和mtr_2的日志刷新到磁盘,那么flushed_to_disk_lsn就应该增长mtr_1和mtr_2写入的日志量,所以flushed_to_disk_lsn的值增长到了9948。综上所述,当有新的redo 日志写入到log buffer 时,首先lsn的值会增长,但flushed_to_disk_lsn不变,随后随着不断有log buffer中的日志被刷新到磁盘上,flushed_to_disk_lsn的值也跟着增长。如果两者的值相同时,说明log buffer 中的所有redo日志都已经刷新到磁盘中了。

Tips:应用程序向磁盘写入文件时其实是先写到操作系统的缓冲区中去,如果某个写入操作要等到操作系统确认已经写到磁盘时才返回,那需要调用一下操作系统提供的fsync函数。其实只有当系统执行了fsync函数后,flushed_to_disk_lsn 的值才会跟着增长,当仅仅把log buffer中的日志写入到操作系统缓冲区却没有显式的刷新到磁盘时,另外的一个称之为write_lsn的值跟着增长。

当然系统的LSN 值远不止我们前面描述的lsn,还有很多。

查看系统中的各种LSN值

我们可以使用SHOW ENGINE INNODB STATUS命令查看当前InnoDB存储引擎中的各种LSN 值的情况,比如:

mysql> show engine innodb status;
+--------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Type   | Name | Status                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                           |
+--------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| InnoDB |      |
=====================================
2021-09-18 06:33:31 0x7fc31017a700 INNODB MONITOR OUTPUT
=====================================
Per second averages calculated from the last 14 seconds
-----------------
BACKGROUND THREAD
-----------------
srv_master_thread loops: 3 srv_active, 0 srv_shutdown, 333033 srv_idle
srv_master_thread log flush and writes: 333036
----------
SEMAPHORES
----------
OS WAIT ARRAY INFO: reservation count 5
OS WAIT ARRAY INFO: signal count 5
RW-shared spins 0, rounds 4, OS waits 2
RW-excl spins 0, rounds 0, OS waits 0
RW-sx spins 0, rounds 0, OS waits 0
Spin rounds per wait: 4.00 RW-shared, 0.00 RW-excl, 0.00 RW-sx
------------
TRANSACTIONS
------------
Trx id counter 7437
Purge done for trx's n:o < 0 undo n:o < 0 state: running but idle
History list length 0
LIST OF TRANSACTIONS FOR EACH SESSION:
---TRANSACTION 421950793795424, not started
0 lock struct(s), heap size 1136, 0 row lock(s)
--------
FILE I/O
--------
I/O thread 0 state: waiting for completed aio requests (insert buffer thread)
I/O thread 1 state: waiting for completed aio requests (log thread)
I/O thread 2 state: waiting for completed aio requests (read thread)
I/O thread 3 state: waiting for completed aio requests (read thread)
I/O thread 4 state: waiting for completed aio requests (read thread)
I/O thread 5 state: waiting for completed aio requests (read thread)
I/O thread 6 state: waiting for completed aio requests (write thread)
I/O thread 7 state: waiting for completed aio requests (write thread)
I/O thread 8 state: waiting for completed aio requests (write thread)
I/O thread 9 state: waiting for completed aio requests (write thread)
Pending normal aio reads: [0, 0, 0, 0] , aio writes: [0, 0, 0, 0] ,ibuf aio reads:, log i/o's:, sync i/o's:
Pending flushes (fsync) log: 0; buffer pool: 0
481 OS file reads, 61 OS file writes, 7 OS fsyncs
0.00 reads/s, 0 avg bytes/read, 0.00 writes/s, 0.00 fsyncs/s
-------------------------------------
INSERT BUFFER AND ADAPTIVE HASH INDEX
-------------------------------------
Ibuf: size 1, free list len 0, seg size 2, 0 merges
merged operations:insert 0, delete mark 0, delete 0
discarded operations:insert 0, delete mark 0, delete 0
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
Hash table size 34679, node heap has 0 buffer(s)
0.00 hash searches/s, 0.00 non-hash searches/s
---
LOG
---
Log sequence number 444745011
Log flushed up to   444745011
Pages flushed up to 444745011
Last checkpoint at  444745002
0 pending log flushes, 0 pending chkp writes
10 log i/o's done, 0.00 log i/o's/second
----------------------
BUFFER POOL AND MEMORY
----------------------
Total large memory allocated 137428992
Dictionary memory allocated 204566
Buffer pool size   8192
Free buffers       7752
Database pages     440
Old database pages 0
Modified db pages  0
Pending reads      0
Pending writes: LRU 0, flush list 0, single page 0
Pages made young 0, not young 0
0.00 youngs/s, 0.00 non-youngs/s
Pages read 403, created 37, written 44
0.00 reads/s, 0.00 creates/s, 0.00 writes/s
No buffer pool page gets since the last printout
Pages read ahead 0.00/s, evicted without access 0.00/s, Random read ahead 0.00/s
LRU len: 440, unzip_LRU len: 0
I/O sum[0]:cur[0], unzip sum[0]:cur[0]
--------------
ROW OPERATIONS
--------------
0 queries inside InnoDB, 0 queries in queue
0 read views open inside InnoDB
Process ID=1, Main thread ID=140475448022784, state: sleeping
Number of rows inserted 0, updated 0, deleted 0, read 8
0.00 inserts/s, 0.00 updates/s, 0.00 deletes/s, 0.00 reads/s
----------------------------
END OF INNODB MONITOR OUTPUT
============================|
+--------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
1 row in set (0.01 sec)

其中:

  • Log sequence number:代表系统中的lsn值,也就是当前系统已经写入的redo日志量,包括写入log buffer中的日志。

  • Log flushed up to:代表flushed_to_disk_lsn的值,也就是当前系统已经写入磁盘的redo日志量。

  • Pages flushed up to:代表flush链表中被最早修改的那个页面对应的oldest_modification属性值。

  • Last checkpoint at:当前系统的checkpoint_lsn 值。

innodb_flush_log_at_trx_commit的用法

为了保证事务的持久性,用户线程在事务提交时需要将该事务执行过程中产生的所有redo日志都刷新到磁盘上。会很明显的降低数据库性能。如果对事务的持久性要求不是那么强烈的话,可以选择修改一个称为innodb_flush_log_at_trx_commit的系统变量的值,该变量有3个可选的值:

  • 0:当该系统变量值为0时,表示在事务提交时不立即向磁盘中同步redo日志,这个任务是交给后台线程做的。这样很明显会加快请求处理速度,但是如果事务提交后服务器挂了,后台线程没有及时将redo日志刷新到磁盘,那么该事务对页面的修改会丢失。

  • 1:当该系统变量值为 时,表示在事务提交时需要将redo日志同步到磁盘,可以保证事务的持久性。1 也是innodb_flush_log_at_trx_commit的默认值。

  • 2:当该系统变量值为2时,表示在事务提交时需要将redo日志写到操作系统的缓冲区中,但并不需要保证将日志真正的刷新到磁盘。这种情况下如果数据库挂了,操作系统没挂的话,事务的持久性还是可以保证的,但是操作系统也挂了的话,那就不能保证持久性了。

InnoDB之redo log相关推荐

  1. 庖丁解InnoDB之REDO LOG

    简介: 数据库故障恢复机制的前世今生一文中提到,今生磁盘数据库为了在保证数据库的原子性(A, Atomic) 和持久性(D, Durability)的同时,还能以灵活的刷盘策略来充分利用磁盘顺序写的性 ...

  2. InnoDB之redo log写入和恢复

    1. 前言 InnoDB使用Buffer Pool来加速数据读写,提升性能的同时也带来了一些问题,为了避免页面频繁刷盘和磁盘随机写,InnoDB引入了WAL机制,先顺序写少量的redo log,再由后 ...

  3. 在文件log 加入commit id_从物理文件理解InnoDB Redo Log

    导读 作为MySQL DBA都应该知道,Redo Log是可被覆盖的,是ACID中的D的最重要的构成部分,也就是关系型数据库中的WAL中的L. Redo Log记录的是redo,那么redo是什么呢? ...

  4. mysql innodb redolog_MySQL · 引擎特性 · InnoDB redo log漫游(转)

    前言 InnoDB 有两块非常重要的日志,一个是undo log,另外一个是redo log,前者用来保证事务的原子性以及InnoDB的MVCC,后者用来保证事务的持久性. 和大多数关系型数据库一样, ...

  5. 新特性速递 | InnoDB redo log archiving(归档)

     导读 MySQL 8.0.17开始支持的redo log归档能干嘛用呢,好吃吗 今天,MySQL 8.0.17发布了,看了下release note,发现果真如之前预期的那样,恢复了redo lo ...

  6. mysql innodb log_MySQL · 引擎特性 · InnoDB redo log漫游

    前言 InnoDB 有两块非常重要的日志,一个是undo log,另外一个是redo log,前者用来保证事务的原子性以及InnoDB的MVCC,后者用来保证事务的持久性. 和大多数关系型数据库一样, ...

  7. InnoDB磁盘架构之redo log

    文章目录 1 问题背景 2 回顾 3 redo log 1 问题背景 前面研究了InnoDB磁盘架构之双写缓冲区,今天来研究InnoDB的redo log. 2 回顾 InnoDB架构如下图所示: 3 ...

  8. Upgrade after a crash is not supported. The redo log was created with Maria的解决办法

    关于[InnoDB] Unsupported redo log format (0). The redo log was created before MySQL 5.7.9的解决办法 利用mkdir ...

  9. 庖丁解InnoDB之UNDO LOG

    简介: Undo Log是InnoDB十分重要的组成部分,它的作用横贯InnoDB中两个最主要的部分,并发控制(Concurrency Control)和故障恢复(Crash Recovery),In ...

最新文章

  1. 设计模式之享元模式学习笔记
  2. 学习笔记Spark(七)—— Spark SQL应用(2)—— Spark DataFrame基础操作
  3. 利用Linux系统生成随机密码的10种方法
  4. 全国计算机等级考试题库二级C操作题100套(第91套)
  5. 超链接标签/<a>标签
  6. Flask Sessions会话
  7. 诗和远方:无题(五十)
  8. SQL注入自动扫描工具中的语句
  9. 图片维度不匹配_内容审核基础:审核方式、流程与审核维度
  10. 消息长度_nsq消息队列源码分析
  11. 第二十节,使用RNN网络拟合回声信号序列
  12. 【编程好习惯】永远将头文件作为定义和引用的桥梁
  13. win10 计算机显示英文,电脑win10系统改了中文之后为何显示还是英文?
  14. 2022-2028年中国农业观光园行业发展战略规划及投资方向研究报告
  15. 爬虫笔记(二)——Beautiful Soup库
  16. 如何压缩图片?手把手教你三种图片缩小的办法
  17. vue 批量下载通用方法
  18. SLG手游的战斗抽象
  19. 电子书各种格式的转换常见问题
  20. 监听器到底是什么,有什么用

热门文章

  1. linux 查询ip归属地的工具,Linux 通过shell查询ip归属地(curl请求转码)
  2. php mysql bootstart_PHP+MySQL+Bootstrap 美食主题博客项目
  3. 600度近视眼恢复方法_近视孩子的家长看看:600度以上近视可致盲,不花钱恢复视力法...
  4. 小何讲进程: 编写Linux守护进程方法详解
  5. 增量学习 (Incremental Learning)
  6. 大声说出我爱你——寒假英语学习总结
  7. IDEA集成camunda-modeler
  8. 【科普向】谁都能看懂的CRC(循环冗余校验)原理
  9. npm installCould not resolve dependency:peer... 原因和解决方案
  10. 阿里云 Linux 3 安装mysql 亲测有效