我们都晓得事件有4种特征:原子性、一致性、断绝性和耐久性,在事件中的操纵,要么悉数实行,要么悉数不做,这就是事件的目标。事件的断绝性由锁机制完成,原子性、一致性和耐久性由事件的redo 日记和undo 日记来保证。所以本篇文章将议论关于事件中的redo和undo的几个问题:
redo 日记与undo日记离别是什么?
redo 怎样保证事件的耐久性?
undo log 是不是是redo log的逆历程?
redo log
Redo 的范例
重做日记(redo log)用来保证事件的耐久性,即事件ACID中的D。现实上它能够分为以下两种范例:
物理Redo日记
逻辑Redo日记
在InnoDB存储引擎中,大部份状况下 Redo是物理日记,纪录的是数据页的物理变化。而逻辑Redo日记,不是纪录页面的现实修正,而是纪录修正页面的一类操纵,比方新建数据页时,需要纪录逻辑日记。关于逻辑Redo日记触及越发底层的内容,这里我们只需要记着绝大数状况下,Redo是物理日记即可,DML对页的修正操纵,均需要纪录Redo.
Redo 的作用
Redo log的重要作用是用于数据库的崩溃恢复
Redo 的构成
Redo log能够简朴分为以下两个部份:
一是内存中重做日记缓冲 (redo log buffer),是易失的,在内存中
二是重做日记文件 (redo log file),是耐久的,保存在磁盘中
什么时刻写Redo?
上面那张图简朴地表现了Redo的写入流程,这里再细说下写入Redo的机遇:
在数据页修正完成以后,在脏页刷出磁盘之前,写入redo日记。注重的是先修正数据,后写日记
redo日记比数据页先写回磁盘
群集索引、二级索引、undo页面的修正,均需要纪录Redo日记。
Redo的团体流程
下面以一个更新事件为例,宏观上把握redo log 流转历程,以下图所示:
第一步:先将原始数据从磁盘中读入内存中来,修正数据的内存拷贝
第二步:生成一条重做日记并写入redo log buffer,纪录的是数据被修正后的值
第三步:当事件commit时,将redo log buffer中的内容革新到 redo log file,对 redo log file采纳追加写的体式格局
第四步:按期将内存中修正的数据革新到磁盘中
redo怎样保证 事件的耐久性?
InnoDB是事件的存储引擎,其经由过程Force Log at Commit 机制完成事件的耐久性,即当事件提交时,先将 redo log buffer 写入到 redo log file 举行耐久化,待事件的commit操纵完成时才算完成。这类做法也被称为 Write-Ahead Log(预先日记耐久化),在耐久化一个数据页之前,先将内存中响应的日记页耐久化。
为了保证每次日记都写入redo log file,在每次将redo buffer写入redo log file以后,默许状况下,InnoDB存储引擎都需要挪用一次 fsync操纵,由于重做日记翻开并没有 O_DIRECT选项,所以重做日记先写入到文件体系缓存。为了确保重做日记写入到磁盘,必需举行一次 fsync操纵。fsync是一种体系挪用操纵,其fsync的效力取决于磁盘的机能,因而磁盘的机能也影响了事件提交的机能,也就是数据库的机能。
(O_DIRECT选项是在Linux体系中的选项,运用该选项后,对文件举行直接IO操纵,不经由文件体系缓存,直接写入磁盘)
上面提到的Force Log at Commit机制就是靠InnoDB存储引擎供应的参数 innodb_flush_log_at_trx_commit
来掌握的,该参数能够掌握 redo log革新到磁盘的战略,设置该参数值也能够许可用户设置非耐久性的状况发作,细致以下:
当设置参数为1时,(默许为1),示意事件提交时必需挪用一次
fsync
操纵,最平安的设置,保证耐久性当设置参数为2时,则在事件提交时只做 write 操纵,只保证将redo log buffer写到体系的页面缓存中,不举行fsync操纵,因而假如MySQL数据库宕机时 不会丧失事件,但操纵体系宕机则能够丧失事件
当设置参数为0时,示意事件提交时不举行写入redo log操纵,这个操纵仅在master thread 中完成,而在master thread中每1秒举行一次重做日记的fsync操纵,因而实例 crash 最多丧失1秒钟内的事件。(master thread是担任将缓冲池中的数据异步革新到磁盘,保证数据的一致性)
fsync
和write
操纵现实上是体系挪用函数,在许多耐久化场景都有运用到,比方 Redis 的AOF耐久化中也运用到两个函数。fsync
操纵 将数据提交到硬盘中,强迫硬盘同步,将一向阻塞到写入硬盘完成后返回,大批举行fsync
操纵就有机能瓶颈,而write
操纵将数据写到体系的页面缓存后马上返回,背面依托体系的调理机制将缓存数据刷到磁盘中去,其递次是user buffer——> page cache——>disk。
除了上面谈到的Force Log at Commit机制保证事件的耐久性,现实上重做日记的完成还要依赖于mini-transaction。
Redo在InnoDB中是怎样完成的?与mini-transaction的联络?
Redo的完成实则跟mini-transaction严密相干,mini-transaction是一种InnoDB内部运用的机制,经由过程mini-transaction来保证并发事件操纵下以及数据库非常时数据页中数据的一致性,但它不属于事件。
为了使得mini-transaction保证数据页数据的一致性,mini-transaction必需遵照以下三种协定:
The FIX Rules
Write-Ahead Log
Force-log-at-commit
The FIX Rules
修正一个数据页时需要取得该页的x-latch(排他锁),猎取一个数据页时需要该页的s-latch(读锁或许称为同享锁) 或许是 x-latch,持有该页的锁直到修正或接见该页的操纵完成。
Write-Ahead Log
在前面论述中就提到了Write-Ahead Log(预先写日记)。在耐久化一个数据页之前,必需先将内存中响应的日记页耐久化。每一个页都有一个LSN(log sequence number),代表日记序列号,(LSN占用8字节,单调递增), 当一个数据页需要写入到耐久化装备之前,请求内存中小于该页LSN的日记先写入耐久化装备
那为何必需要先写日记呢?可不能够不写日记,直接将数据写入磁盘?原则上是能够的,只不过会发生一些问题,数据修正会发生随机IO,但日记是递次IO,append体式格局递次写,是一种串行的体式格局,如许才充分利用磁盘的机能。
Force-log-at-commit
这一点也就是前文提到的怎样保证事件的耐久性的内容,这里再次总结一下,与上面的内容相照应。在一个事件中能够修正多个页,Write-Ahead Log 能够保证单个数据页的一致性,然则没法保证事件的耐久性,Force-log-at-commit 请求当一个事件提交时,其发生一切的mini-transaction 日记必需革新到磁盘中,若日记革新完成后,在缓冲池中的页革新到耐久化存储装备前数据库发作了宕机,那末数据库重启时,能够经由过程日记来保证数据的完整性。
重做日记的写入流程
上图示意了重做日记的写入流程,每一个mini-transaction对应每一条DML操纵,比方一条update语句,其由一个mini-transaction来保证,对数据修正后,发生redo1,起首将其写入mini-transaction私有的Buffer中,update语句完毕后,将redo1从私有Buffer拷贝到公有的Log Buffer中。当全部外部事件提交时,将redo log buffer再刷入到redo log file中。
undo log
undo log的定义
undo log重要纪录的是数据的逻辑变化,为了在发作错误时回滚之前的操纵,需要将之前的操纵都纪录下来,然后在发作错误时才够回滚。
undo log的作用
undo是一种逻辑日记,有两个作用:
用于事件的回滚
MVCC
关于MVCC(多版本并发掌握)的内容这里就不多说了,本文重点关注undo log用于事件的回滚。
undo日记,只将数据库逻辑地恢复到本来的模样,在回滚的时刻,它现实上是做的相反的事情,比方一条INSERT ,对应一条 DELETE,关于每一个UPDATE,对应一条相反的 UPDATE,将修正前的行放归去。undo日记用于事件的回滚操纵进而保证了事件的原子性。
undo log的写入机遇
DML操纵修正聚簇索引前,纪录undo日记
二级索引纪录的修正,不纪录undo日记
需要注重的是,undo页面的修正,一样需要纪录redo日记。
undo的存储位置
在InnoDB存储引擎中,undo存储在回滚段(Rollback Segment)中,每一个回滚段纪录了1024个undo log segment,而在每一个undo log segment段中举行undo 页的请求,在5.6之前,Rollback Segment是在同享表空间里的,5.6.3以后,可经由过程 innodb_undo_tablespace设置undo存储的位置。
undo的范例
在InnoDB存储引擎中,undo log分为:
insert undo log
update undo log
insert undo log是指在insert 操纵中发生的undo log,由于insert操纵的纪录,只对事件自身可见,对其他事件不可见。故该undo log能够在事件提交后直接删除,不需要举行purge操纵。
而update undo log纪录的是对delete 和update操纵发生的undo log,该undo log能够需要供应MVCC机制,因而不能再事件提交时就举行删除。提交时放入undo log链表,守候purge线程举行末了的删除。
补充:purge线程两个重要作用是:清算undo页和消灭page内里带有Delete_Bit标识的数据行。在InnoDB中,事件中的Delete操纵现实上并非真正的删撤除数据行,而是一种Delete Mark操纵,在纪录上标识Delete_Bit,而不删除纪录。是一种"假删除",只是做了个标记,真正的删除事情需要背景purge线程去完成。
undo log 是不是是redo log的逆历程?
undo log 是不是是redo log的逆历程?实在从前文就能够得出答案了,undo log是逻辑日记,对事件回滚时,只是将数据库逻辑地恢复到本来的模样,而redo log是物理日记,纪录的是数据页的物理变化,明显undo log不是redo log的逆历程。
redo & undo总结
下面是redo log + undo log的简化历程,便于明白两种日记的历程:
假设有A、B两个数据,值离别为1,2. 1. 事件最先 2. 纪录A=1到undo log 3. 修正A=3 4. 纪录A=3到 redo log 5. 纪录B=2到 undo log 6. 修正B=4 7. 纪录B=4到redo log 8. 将redo log写入磁盘 9. 事件提交
现实上,在insert/update/delete操纵中,redo和undo离别纪录的内容都不一样,量也不一样。在InnoDB内存中,平常的递次以下:
写undo的redo
写undo
修正数据页
写Redo
小结
本文剖析了事件中的redo和undo日记,参考了一些材料书本整顿得出,能够有些处所表述的不清楚。若有不对的地方,迎接指出。
以上就是MySQL事件中的redo与undo的剖析(图文)的细致内容,更多请关注ki4网别的相干文章!