为什么会产生回滚与前退

于一个 oracle 概念问题,如果数据没有提交,但是却被 dbwn 进程写入了数据文件,会怎么样呢?

解释如下:

首先说明的是dbwn写脏数据跟commit提交没有关系!

在一个 transaction 发生的过程中, online redo log 首先记录 transaction 中修改的数据块相关信息,修改的数据块会被缓存在 database buffer cache 中。由于 database buffer cache 写满或者 checkpoint 等等条件触发 dbwn 进程,会导致这些缓存的数据块写入数据文件,但此时可能该 transaction 仍然还没有提交。所以在数据文件中,可能会有 commited   uncommited  的数据块。而原有的数据块镜像会存放在 undo segment
IXDBA.NET社区论坛

然而, dbwn 写脏数据时不管这个要写的 transaction 是否提交,
也没有必要去管。

这样就发生了所谓的已经提交的数据,但是还没有写入数据文件的现象。
还有一种情况,数据没有提交,但是已经被写入数据文件,此时发生回退,撤销没有提交的数据。

那么,引发oracle前滚与回退的根本原因就是什么呢?

根本原因是 commit 后写 redo buffer 和触发 lgwr  redo buffer 的区别。
事务在执行完毕后,随即会被写入 redo buffer undo 中,同时在 redo buffer undo 中对该事务都有一个是否提交的标记。两者的默认状态都是 active 的,即没有提交时刻处于激活状态。

commit
操作执行时刻把此前的所有事务操作全部写入 redo log file commit 成功后, redo buffer 信息全部写入 redo file ,同时修改两者中的事务提交标识为 inactive ,表示此前事务已经递交。

oracle
的前滚和回退根据就是依据事务是否提交而进行的。

在触发 lgwr 进程后, oracle 同样把此前的 redo buffer 信息写入 redo file ,但是与 commit 触发写日志不同的是, redo file 本身对 lgwr 写日志操作不记录任何信息标识, lgwr 写到那里就是那里,就算此时掉电也无妨, redo file 就记录到掉电时刻的信息。

lgwr
是一个 oracle 后台执行的进程,具体的日志写操作都有 oracle 去控制,这对于 oracle 来说是透明的,因此不用在 redo file 中写入任何标记信息,这也是正常的。

commit
操作是唯一一个可以前台操作与 oracle 后台通信的指令,因此当加入这个操作以后, oracle 本身必须要了解各个事务的读写状况,那么怎么了解整个状况:在 redo 以及 undo 中加入是否递交的标识,对于已经提交的操作,但是还没有写入数据文件,那么就要前滚,相反,对于没有提交,执行回退!
于是, oracle 崩溃恢复步骤如下:

首先 rolling forward  前滚:由于 oracle failure sga 中的内存信息丢失了,但是 online redo log 中还是存储了 transaction 信息,包括 commited or uncommited data 。可能这些修改信息并没有被 oracle 正确的来处理,包含两种情况:已经提交的还没有写入数据文件,或者没有提交的却被写入了数据文件。针对已经提交的还没有写入数据文件就要发生前滚,在前滚过程中, smon 会根据 online redo log 中的记录来完成对 datafile 的修改。保证已经提交的数据已经写入数据文件。  

接下来,前滚结束后,数据库正常 open ,此时用户可以正常连接,可以访问已经 recover commited data ,但是对于那些属于 unrecoverable transaction uncommited data ,会被 oracle  加锁,是不可以访问的。

最后,  rolling back :如果有进程访问这些加锁的 data ,此时 smon 会对这些数据块做 rollback 回滚,从数据文件中撤销没有提交却被写入数据文件的数据。

至此,这个问题完全被剖析。

你可能感兴趣的:(数据库,职场,回滚,休闲,前滚)