W4.2 undo log redo log 和事务原理

来源:互联网 发布:知乎日报 大误 编辑:程序博客网 时间:2024/06/05 03:24

知识准备:

MVCC:多版本并发控制;

 

LSNlog sequence number用于记录日志序号,它是一个不断递增的 unsigned long long类型整数。在InnoDB的日志系统中,LSN无处不在,它既用于表示修改脏页时的日志序号,也用于记录checkpoint,通过LSN,可以具体的定位到其在redo log文件中的位置

 

ACID:事务的四个基本特性。包含:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)、持久性(Durability);

 

WALWrite-Ahead Logging预写日志系统。主要是保证数据库的可恢复性

WAL 的中心思想是对数据文件的修改(它们是表和索引的载体)必须是只能发生在这些修改已经记录了日志之后, 也就是说,在描述这些变化的日志记录冲刷到永久存储器之后。 如果我们遵循这个过程,那么我们就不需要在每次事务提交的时候都把数据页冲刷到磁盘,因为我们知道在出现崩溃的情况下, 我们可以用日志来恢复数据库:任何尚未附加到数据页的记录都将先从日志记录中重做(这叫向前滚动恢复,也叫做重做或redo)。

 

InnoDB 有两块非常重要的日志,一个是undo log,另外一个是redo log,前者用来保证事务的原子性以及InnoDBMVCC,后者用来保证事务的持久性。

 

什么是redo log:

记录事务操作或是事务操作对应的底层变化内容,所有的DML都会被redo log记录。

产生的背景:

InnoDBDML操作会首先在buffer poolpage上进行,被DMLPage将被标记为dirty并被放到专门的flush list上,MySQL的主进程或专门的刷脏线程,定时或者在特定条件下将这些页面写入磁盘。这样的好处是避免每次写操作都操作磁盘导致大量的随机IO,可以将多次对页面的修改merge成一次IO操作,同时异步写入也降低了访问的时延。

然而,如果在dirty page还未刷入磁盘时,server非正常关闭,这些修改操作将会丢失,如果写入操作正在进行,甚至会由于损坏数据文件导致数据库不可用。为了避免上述问题的发生,InnoDB将所有对页面的修改操作写入一个专门的文件,并在数据库启动时从此文件进行恢复操作,这个文件就是redo log file。这样的技术推迟了buffer pool页面的刷新,从而提升了数据库的吞吐,有效的降低了访问时延。带来的问题是额外的写redo log操作的开销(顺序IO,当然很快),以及数据库启动时恢复操作所需的时间。这也就是说redo log 可以保证事务的持久性不受外界因素影响。

InnoDBredo log可以通过参数innodb_log_files_in_group配置成多个文件,另外一个参数innodb_log_file_size表示每个文件的大小。因此总的redo log大小为innodb_log_files_in_group * innodb_log_file_size

Redo log文件以ib_logfile[number]命名,默认是放在数据库的根目录下,日志目录可以通过参数innodb_log_group_home_dir控制。Redo log 以顺序的方式写入文件文件,写满时则回溯到第一个文件,进行覆盖写。(但在做redo checkpoint时,也会更新第一个日志文件的头部checkpoint标记,所以严格来讲也不算顺序写)。

 

InnoDB内部,逻辑上ib_logfile被当成了一个文件,对应同一个space id。由于是使用512字节block对齐写入文件,可以很方便的根据全局维护的LSN号计算出要写入到哪一个文件以及对应的偏移量。

Redo log文件是循环写入的,在覆盖写之前,总是要保证对应的脏页已经刷到了磁盘。在非常大的负载下,Redo log可能产生的速度非常快,导致频繁的刷脏操作,进而导致性能下降,通常在未做checkpoint的日志超过文件总大小的76%之后,InnoDB认为这可能是个不安全的点,会强制的preflush脏页,导致大量用户线程stall住。如果可预期会有这样的场景,我们建议调大redo log文件的大小。可以做一次干净的shutdown,然后修改Redo log配置,重启实例。

 

什么是undo log

记录事务的逆操作,或是事务操作对应的底层逆变换的内容。

产生的背景:

Undo Log的原理说起来很简单,为了满足事务的原子性,在操作任何数据之前,该操作的反操作记录到一个地方。然后进行数据的修改。如果出现了错误或者用户执行了ROLLBACK语句,系统可以利用UndoLog中的备份将数据恢复到事务开始之前的状态。除了可以保证事务的原子性,Undo Log也可以用来辅助完成事务的持久化。

undo log回滚日志是保存在共享表空间ibdata1文件里,可以通过一系列的参数将其从共享表空间中独立出来,独立表空间和共享表空间各有长短,这里不做论述。

 

通过事务的简单示意 undo redo直接的关系。

假设有AB两个数据需要修改,值分别为1,2,将A update3B update4

 

A.事务开始.

B.记录A=1undolog.

C.修改A=3.

D.记录A=3redolog.

E.记录B=2undolog.

F.修改B=4.

G.记录B=4redolog.

H.redolog写入磁盘。

I.事务提交

 

这是一个非常简单的案例,如果读者有兴趣,可以参考何登成前辈的共享《InnoDB 日志 回滚段 & 崩溃恢复实现详解》

里面详细的说明了每种DMLundoredo是怎么实现ACID的。

 

 

参考文章:

http://www.cnblogs.com/liuhao/p/3714012.html

 

http://mysql.taobao.org/monthly/2015/05/01/

 

http://wenku.baidu.com/link?url=q8ZRVQf87xNTzkR8hJY5q4CCMeeXHu-XLchxKjyYzu8Wb9yOVOf4QGHE7sVblb4TvG0OfUdjn8HcRMSpIJlIUDHHB4vsKyw46rYeFFCeqYW

原创粉丝点击