MySQL的InnoDB引擎日志工作原理

有运维或运维开发方面的需求,可以联系博主QQ 452336092或Email:admin#centos.bz(收费)

当你使用UPDATE, INSERT, DELETE语句更新数据的时候,你就改变了两个地方的数据:log buffer和data buffers。Buffers是固定长度的内存块,通常是512字节。

LOG BUFFER           DATA BUFFER
=================    ===============
= Log Record #1 =    = Page Header =
= Log Record #2 =    = Data Row    =
= Log Record #3 =    = Data Row    =
= Log Record #4 =    = Data Row    =
=================    ===============

例如:INSERT INTO JOBS VALUES(1,2,3)语句执行之后,log buffer将增加一个新的log记录,称为Log Record #5,它包含一个rowid和新记录的内容。同时,data buffer也将增加一个新行,但是,它会同时在页头标识:该页最新的log记录是Log Record #5。在这个例子中#5是Log Sequence Number(LSN),它对于接下来操作的时序安排是至关重要的。

下面是data-change的一些细节:

1、一个INSERT log记录仅包含一个新数据,它对于在页上重做操作是足够的了,因此被称为一个redo条目。

2、LSN不是log记录的一个域,它是文件中的一个绝对地址的相对偏移值。
InnoDB改变了log buffer和data buffer之后,接下来就是写盘了。这就是复杂的地方。有多个线程在监控buffer的活动情况,有三种情况――overflow, checkpoint和commit――可以导致写盘操作。

Overflows情况下发生了什么?

Overflow是很少发生的情况,因为InnoDB采用pro-active措施来防止buffers被填满。但是我们还是来看看下面两种情况:

1、如果log buffer满了,InnoDBInnoDB在buffer的末尾写log。那么情况向下面的图一样(log buffer只有四条记录的空间,现在插入第五条记录):

LOG FILE(S) BEFORE WRITING LOG RECORD #5
=================
= Log Record #1 =
= Log Record #2 =
= Log Record #3 =
= Log Record #4 =
=================

LOG FILE(S) AFTER WRITING LOG RECORD #5
=================
= Log Record #5 =
= Log Record #2 =
= Log Record #3 =
= Log Record #4 =
=================

logs不可能永远增长。即使InnoDB使用了某些压缩算法,log文件还是会由于太大而不能放到任何磁盘驱动器上。因此InnoDB采取循环写的办法,也就是说将会覆盖前面就的log记录。

2、如果data buffer满了,InnoDB将最近使用的buffer写入到数据库中,但是不可能足够的快。这种情况下,页头的LSN就起作用了。第一,InnoDB检查它的LSN是否比log文件中最近的log记录的LSN大,只有当log赶上了data的时候,才会将数据写到磁盘。换句话说,数据页不会写盘,直到相应的log记录需要写盘的时候。这就是先写日志策略。

CheckPoints的时候发生了什么?

前面说过InnoDB采取了一些pro-active措施来保证不发生overflows,其中最重要的措施就是checkpointing。有一个分离的线程,或者说从一组修改buffers的线程中分离出来的一个线程。在特定的时间间隔,checkpointer将醒来,检查buffer的改变,并保证写盘操作已经发生了。

大部分DBMS在这个时候,将会把所有的buffer写盘,这样可以保证所有改变了但是没写盘的buffer都写盘。就是说DBMS将通过”Sharp Checkpoint” flush所有”dirty”buffers。但是InnoDB只保证:(a)log和data buffers不会超过某个限制点;(b)log始终比data先写盘;(c)没有哪个data buffer的页头LSN等于被覆盖写的log记录。也就是说InnoDB是”Fuzzy Checkpoint”。

在COMMIT的时候,InnoDB不会将dirty data page写盘。之所以强调这个是因为,很容易让人想到,提交改变就是将所有东西写到一个持久媒介上。其实,只有log记录需要写。写dirty data page只可能发生在overflow或checkpoint时刻,因为它们的内容是多余的。

Recovery

在recovery里面可以看到log是非常必要的:当数据库发生异常的时候,数据是可以恢复的。
对于不是损坏磁盘驱动器的异常,恢复是自动进行的。InnoDB读取最新的checkpoint日志记录,检查dirty pages是否在异常发生前写到磁盘上了,如果没有,则读取影响该页的log记录并应用它们。这被称为”rolling forward”。因为有LSN,所以InnoDB只需要比较这个数字就可以进行同步。

原文出处:chinaunix -> http://blog.chinaunix.net/uid-20761674-id-75092.html

打赏

如果此文对你有所帮助,请随意打赏鼓励作者^_^