介绍数据库中的wal技术_【数据库】持久化与故障恢复

本文介绍了数据库中的持久化与故障恢复技术,重点讲解了Undo、Redo和WAL(预写日志)的概念。WAL确保数据在磁盘上的修改在日志记录被持久化后进行,提高了数据一致性和系统性能。检查点和快照也是重要的恢复机制,用于减少恢复时间。介质故障时,可通过RAID技术提供的冗余恢复数据。
摘要由CSDN通过智能技术生成

2647203adf58d829a533c58462b00bc8.png

数据库中实现持久化与故障恢复的技术有很多,下面主要对Undo、Redo、WAL、Checkpoint、Snapshot等相关技术进行记录一、Undo和Redo
暂且这样称呼:
数据库文件data file;
数据库缓存db buffer;
日志缓存log buffer;
磁盘日志文件log file;
某次操作,我们取了数据库某表格中的数据,这个数据会在内存中缓存一些时间。对这个数据的修改在开始时候也只是修改在内存中的内容。当db buffer已满或者遇到其他的情况,这些数据会写入data file。log file一般是追加内容,可以认为是顺序写,顺序写的磁盘IO开销要小于随机写。Undo日志记录某数据被修改前的值,可以用来在事务失败时进行rollbackRedo日志记录某数据块被修改后的值,可以用来恢复未写入data file的已成功事务更新的数据
简单举个例子说明(实际过程比这要复杂的多):
1、当你发出一条update语句后,oracle先将更改前后信息写进redo(当满足一定条件后由日志写进程写入日志文件)
2、然后将更新前得数据镜像copy到undo中。
3、用户rollback后,oracle 将undo中的数据覆盖回去
用户commit后,oracle可以根据redo 的信息进行数据恢复。(当然也可以利用undo进行flashback)
例如某一事务的事务序号为T1,其对数据X进行修改,设X的原值是5,修改后的值为15,那么Undo日志为<T1, X, 5>,Redo日志为<T1, X, 15>。也有把undo和redo结合起来的做法,叫做Undo/Redo日志,在这个例子中Undo/Redo日志为<T1, X, 5, 15>
当用户生成一个数据库事务时,undo log buffer会记录被修改的数据的原始值,redo会记录被修改的数据更新后的值。
redo日志应首先持久化在磁盘上,然后事务的操作结果才写入db buffer,(此时,内存中的数据和data file对应的数据不同,我们认为内存中的数据是脏数据),db buffer再选择合适的时机将数据持久化到data file中。这种顺序可以保证在需要故障恢复时恢复最后的修改操作。先持久化日志的策略叫做Write Ahead Log,即预写日志。
在很多系统中,undo日志并非存到日志文件中,而是存放在数据库内部的一个特殊段中。本文中就把这些存储行为都泛化为undo日志存储到undo log file中。对于某事务T,在log file的记录中必须开始于事务开始标记(比如“start T”),结束于事务结束标记(比如“end T”、”commit T”)。在系统恢复时,如果在log file中某个事务没有事务结束标记,那么需要对这个事务进行undo操作,如果有事务结束标记,则redo。
在db buffer中的内容写入磁盘数据库文件之前,应当把log buffer的内容写入磁盘日志文件。
有一个问题,redo log buffer和undo log buffer存储的事务数量是多少,是按照什么规则将日志写入log file?如果存储的事务数量都是1个,也就意味着是将日志立即刷入磁盘,那么数据的一致性很好保证。在执行事T时,突然断电,如果未对磁盘上的redo log file发生追加操作,可以把这个事务T看做未成功。如果redo log file被修改,则认为事务是成功了,重启数据库使用redo log恢复数据到db buffer和 data file即可。
如果存储多个的话,其实也挺好解释的。就是db buffer写入data file之前,先把日志写入log file。这种方式可以减少磁盘IO,增加吞吐量。不过,这种方式适用于一致性要求不高的场合。因为如果出现断电等系统故障,log buffer、db buffer中的完成的事务会丢失。以转账为例,如果用户的转账事务在这种情况下丢失了,这意味着在系统恢复后用户需要重新转账。


基本日志
基本日志的主要内容包括:

  • 事务标识符T -> 执行写操作事务的唯一标识符
  • 数据项标识符X -> 操作对象(被修改的数据项)的唯一标识符
  • 前像V1 -> 更新前数据的值
  • 后像V2 -> 更新后数据的值

基本的日志记录形式

  • 表示事务T已经开始
  • 表示事务T已经提交
  • 表示事务不能成功完成,已终止
  • 表示事务T对数据项X执行写操作,写之前的旧值为V1,写之后的新值为V2

不同的执行对应的恢复策略
在执行更新事务的时候,根据后像写入磁盘的时间不同,有对应3种方案进行回滚(1) 后像在事务提交后才写入磁盘

dd2dd49f09a6cf1839cfb94347c38c13.png


在这种情况下,使用日志进行回滚的步骤为:
1.从后向前扫描日志,将提交的事务放在redo-list队列中
2.从日志文件开始处扫描,对遇到的每个
if T in redo-list{
X = V
}else{
logFile.nextLog()
}
3.对于未完成的事务,在日志中写入一个并刷新日志(2) 后像在事务提交之前完全写入磁盘

bb019d4d7ea5e8c0c729b9703b233d7e.png


在这种情况下,使用日志进行回滚的步骤为:
1.从后向前扫描日志,将提交的事务放在redo-list队列中
2.从日志文件开始处扫描,对遇到的每个
if T !in redo-list{
X = V
}else{
logFile.nextLog()
}(3) 后像在事务提交前后写入磁盘

49a636c15e849a7dab8a0cf936a18a18.png


在这种情况下,使用日志进行回滚的步骤为:
if T.commited {
redo(T) //更新事务所有数据项
}else{
undo(T) //将事务所有数据项设置为前像
}二、WAL


预写日志WAL(即Write-Ahead Logging)是保证数据完整性的一种标准方法。简单来说,WAL的中心概念是数据文件(存储着表和索引)的修改必须在这些动作被日志记录被刷到持久存储之后才被写入。如果我们遵循这种过程,我们不需要在每个事务提交时刷写数据页面到磁盘,因为我们知道在发生崩溃时可以使用日志来恢复数据库:任何还没有被应用到数据页面的改变可以根据其日志记录重做(这是前滚恢复,也被称为REDO)。Tip: 因为WAL在崩溃后恢复数据库文件内容,不需要日志化文件系统作为数据文件或WAL文件的可靠存储。实际上,日志会降低性能,特别是如果日志导致文件系统数据被刷写到磁盘。幸运地是,日志期间的数据刷写常常可以在文件系统挂载选项中被禁用,例如在Linux ext3文件系统中可以使用data=writeback。在崩溃后日志化文件系统确实可以提高启动速度。使用WAL可以显著降低磁盘的写次数,因为只有日志文件需要被刷出到磁盘以保证事务被提交,而被事务改变的每一个数据文件则不必被刷出。日志文件被按照顺序写入,因此同步日志的代价要远低于刷写数据页面的代价。在处理很多影响数据存储不同部分的小事务的服务器上这一点尤其明显。此外,当服务器在处理很多小的并行事务时,日志文件的一个fsync可以提交很多事务。预写日志的原理:修改并不直接写入到数据库文件中,而是写入到另外一个称为WAL的文件中;如果事务失败,WAL中的记录会被忽略,撤销修改;如果事务成功,它将在随后的某个时间被写回到数据库文件中,提交修改。
读时,在WAL文件中搜索,找到最后一个写入点,记住它,并忽略在此之后的写入点(这保证了读写和读读可以并行执行);随后,它确定所要读的数据所在页是否在WAL文件中,如果在,则读WAL文件中的数据,如果不在,则直接读数据库文件中的数据。
写时,写入到WAL文件中即可,但是必须保证独占写入,因此写写之间不能并行执行。

  • 优点
  • 1.读和写可以完全地并发执行,不会互相阻塞(但是写之间仍然不能并发)。
  • 2.WAL在大多数情况下,拥有更好的性能(因为无需每次写入时都要写两个文件,减少磁盘I/O)。
  • 3.磁盘I/O行为更容易被预测。
  • 缺点
  • 当写入数据很大或者事务很长的时候,数据库性能将下降。因为这将导致WAL文件长时间被占用,并且WAL文件的大小将会很大,增加寻址时间。

三、检查点
利用日志进行数据库恢复的时候,通常需要探索整个日志才能确定哪些事务需要redo,那些需要undo,这样会导致:

  • 搜索整个日志消耗大量时间
  • 许多需要redo的事务的更新操作已经写入磁盘,redo将浪费大量时间

检查点(Checkpoint)是一个数据库事件,它把当前内存中已修改的页(称为“脏页” )和事务日志信息从高速缓存写入磁盘,并更新控制文件和数据文件记录有关事务日志的信息它存在的根本意义在于减少崩溃恢复(Crash Recovery)时间
结合前面的Undo和Redo:检查点(checkpoint)是为了定期将db buffer的内容刷新到data file。当遇到内存不足、db buffer已满等情况时,需要将db buffer中的内容/部分内容(特别是脏数据)转储到data file中。在转储时,会记录checkpoint发生的”时刻“。在故障回复时候,只需要redo/undo最近的一次checkpoint之后的操作。
检查点技术让系统不定期的简历检查点,保存数据库的状态,当需要恢复扫描日志文件时候只用到达就能停止。创建检查点的3种方法有:

  • 提交一致性检查点
  • 高速缓存一致性检查点
  • 模糊一致性检查点

提交一致性检查点建立时候需要等待所有活动事务全部提交,在等待过程中新的事务不能开始,这将导致系统的阻塞。高速缓存一致性检查点建立时候不用等待活动事务提交,只需要保证事务不执行更新操作就可建立,提高恢复过程的效率。模糊一致检查点去除高速缓存一致性检查点建立时候事务暂停的限制,允许事务在checkpoint---缓存写入磁盘之间更新。磁盘上需要维护一个last-chackpoint信息,当缓冲区的数据刷盘完成时候才会更新,以此应对系统在checkpoint---缓存写入磁盘之间崩溃。Oracle中的检查点
当修改数据时,需要首先将数据读入内存中(Buffer Cache),修改数据的同时,Oracle会记录重做信息(Redo)用于恢复。因为有了重做信息的存在,Oracle不需要在提交时立即将变化的数据写回磁盘(立即写的效率会很低),重做(Redo)的存在也正是为了在数据库崩溃之后,数据就可以恢复。
最常见的情况,数据库可以因为断电而Crash,那么内存中修改过的、尚未写入文件的数据将会丢失。在下一次数据库启动之后,Oracle可以通过重做日志(Redo)进行事务重演,也就是进行前滚,将数据库恢复到崩溃之前的状态,然后数据库可以打开提供使用,之后Oracle可以将未提交的数据进行回滚。
在这个过程中,通常大家最关心的是数据库要经历多久才能打开。也就是需要读取多少重做日志才能完成前滚。当然用户希望这个时间越短越好,Oracle也正是通过各种手段在不断优化这个过程,缩短恢复时间。检查点的存在就是为了缩短这个恢复时间。
当检查点发生时(此时的SCN被称为CheckPoint SCN),Oracle会通知DBWR进程,把修改过的数据,也就是Checkpoint SCN之前的脏数据(Dirty Data)从Buffer Cache写入磁盘,当写入完成之后,CKPT进程更新控制文件和数据文件头,记录检查点信息,标识变更。四、Snapshot
SNIA(存储网络行业协会)对快照的定义:关于指定数据集合的一个完全可用拷贝,该拷贝包括相应数据在某个时间点(拷贝开始的时间点)的映像。快照可以是其所表示的一个副本,也可以是数据的一个复制品。
从技术角度,快照其实是指向保存在存储设备中的数据的引用标记或指针,说穿了就是数据在某一时刻的状况,其工作原理核心就是是建立一个指针列表,指示读取数据的地址,提供一个瞬时数据的影像,当数据有改变时,再进行复制
快照是数据库在某一时间点的视图,快照并不复制整个数据库的页,而是仅仅复制在快照建立时间点之后改变的页。
数据库取数据库的原理是这样的:快照生成之后,如果数据库中任何数据页都没有被修改(insert,delete,update等),这个时候快照的mdf文件是空的,几乎不占用任何磁盘空间,这个时候从数据库快照中取数据库其实还是从源数据库中取。快照生成之后,数据库中的数据发生变动,这个时候数据库快照的mdf文件中就有了数据,但是只限于刚刚被修改之前的数据。
举例 :10 被修改为 100,这个时候数据库快照中存放10,源数据库中存放100.如果从数据库快照中去的数据既有被修改的也有没有被修改的,修改部分从数据库快照的mdf文件中获得,没有被修改的还是从源数据库中获得。五、介质故障
RAID(磁盘阵列技术)将一组磁盘驱动器使用逻辑的方式连接起来,对上层用户透明,作为逻辑上的一个磁盘驱动器使用。RAID通过冗余技术,提供一个高级别的数据保护措施。
优点:

  • 成本低,功耗小,传输速率高
  • 可以提供容错能力
  • 具有数据校验能力

介质故障的恢复使用备份将数据恢复到一个一致性状态,再使用redo将数据尽可能的恢复。
喜欢本文的朋友欢迎点赞分享~

63dae35f57e873ea0776d75a0a466091.png

唯识相链启用微信交流群(Go与区块链技术)

欢迎加微信:ywj2271840211

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值