以下摘自一本ORACLE书
在缓存恢复期间,Oracle 重放自上次检查点以来联机重做日志文件中的事务。在此前滚操作期间,已提交和未提交的更改都应用于数据文件。在前滚操作结束时,数据文件将具有已提交的更改、写入数据文件以释放缓冲区高速缓存空间的未提交更改以及前滚操作应用的未提交更改。一旦缓存恢复完成,就可以打开数据库。
上面粗体的句子是我不明白的。重做日志文件如何生成未提交的数据,因为它的所有信息都在 COMMIT 之后记录?
进一步说
在实例恢复的事务恢复阶段,Oracle 应用撤消块来回滚数据块中未提交的更改,这些更改要么是在实例崩溃之前写入的,要么是在缓存恢复期间由前滚操作进行的。
我知道如果在没有事先提交(如果可能的话)的情况下将脏块写入磁盘,在事务恢复期间,可以使用撤消块将它们回滚。但是如何使用撤消块来回滚在缓存恢复期间通过重放重做日志引入的未提交的更改(无论如何这些更改是什么......)?
嗯,我不明白,因为联机重做日志应该只包含已提交的信息,但在实例恢复期间会创建未提交的信息。
LGWR
当-DBWn
进程将脏缓冲区写入磁盘。这些都触发重做刷新,其中可能包括未提交的事务。
让我举个例子,假设你有一个数据块,其中包含一行,单列的值为
5
。您只需尝试使用update tbl set col1=6
. 在这个过程中会产生undo来重现它的原始值 is5
并产生redo来回复事务,意思是重现最新的值 is6
。接下来,如果这个事务未提交并且不幸的是实例崩溃,在下一次启动期间,Oracle(特别
SMON
是进程)将需要恢复的块放入缓冲区缓存并使用重做日志重新应用更改,如果有人试图读取对于您之前修改过的行,Oracle 只是使用 undo 将包含该行的数据块回滚到其原始值 5。更新: 以下警报日志摘录自该博客。
这清楚地表明块号
1721
需要恢复。为了做到这一点,块被加载到内存(缓冲区缓存)中并应用重做。该块在恢复后被写回数据文件。Thomas Kyte 在(第 9 章重做和撤消,重做和撤消如何协同工作,第 3 版)Expert Oracle Architecture 一书中也对此进行了解释。
来自 ASKTOM
实例/崩溃恢复