Oracle前滚和Oracle后滚的学习案例

案例(1)

就假设我修改了一条数据:update people set name='Fusnow' where name='old fusnow';

那我需要做的事情包括:

在redo log buffer生成redo信息(包括对表的redo,undo的redo,索引什么的就不考虑了)

在buffer cache里修改name='Fusnow',修改undo segment

------------------

情况1

如果一切正常,我现在commit,commit会触发lgwr把redo log buffer里的信息写入到磁盘的redo log file,如果这个操作成功完成,那我的数据安全了,现在如果系统崩溃,尽管可能会丢失buffer cache里的脏数据,但可以从redo log里找到重做信息,所以,可以恢复,当然这个情况不用rollback。

------------------

情况2

如果lgwr把redo log buffer里的信息写入到磁盘的redo log file的过程中系统就崩了,那实际上对用户而言commit没有成功就报错了,这时候datafile和redo log上都没有我们要的信息,所以正好,系统启动的时候我这个改动的roll forward/back 都省了。

------------------

情况3

如果commit之前,有什么原因导致我们要flush buffer cache,比如buffer cache满了,oracle要吧buffer cache里的dirty data写入到磁盘,这要触发dbwr,但dbwr写之前一定要触发lgwr,先把redo log buffer里的数据写入到redo log file。原因很简单,如果不触发lgwr,由于对于我的这个改变的脏数据包括表的改动和undo改动,而dbwr很可能不是在一次io里面把这些脏数据写入磁盘,如果就是这么巧,我们先写入了表的改动,还没来得及写undo的脏数据,数据库崩了,那现在我们的状态是datafile里面有改过的表数据,没有undo数据,redo里面没有redo信息,由于我是没有commit,所以要回滚,但这种情况下是不可能的,因为undo丢了,可以重新生成undo的redo也丢了。因此,dbwr一定要触发lgwr。

如果在dbwr触发lgwr的前提下,我们先写入了表的改动,还没来得及写undo的脏数据的时候数据库崩了,我们实际上是先roll forward,通过redo生成undo,再rollback,通过undo回滚事务。

当然,有兄弟也提过了了,先后顺序是1.roll forward, 2.open database, 3.rollback,我想这主要是oracle为了节省时间,因为设计上按照1.roll forward, 2.rollback, 3.open database的顺序应该也是可以的,但这样比较慢,我们完全可以在roll forward结束后马上open database,然后让用户访问数据库的其他部分,让smon慢慢rollback,这时候如果用户想访问正被回滚的数据是会被堵塞的。当然,在fast模式下,oracle会优先rollback用户想访问的block,让用户尽快可以访问这些正被rollback的数据。

案例(2)

假定有一下操作语句:

update gaojf set  name='exitgogo' where name='old_exitgogo';

这个语句是这样执行的:

1:首先检查name='old_exitgogo'是否记录在buffer cache中,如果不在,读取到buffer中。

本文URL地址:http://www.bianceng.cn/database/Oracle/201410/45542.htm

2:在回滚段表空间的相应回滚段事务表中分配事务段,这个操作产生redo信息。

3:从回滚段中读入或者在buffer中或者说是在buffer cache中创建name='old_exitgogo'的前镜像,这个操作同样产生redo信息并记录写入redo buffer。

4:在数据缓冲区修改name='exitgogo',这个操作的日志信息也写入redo buffer。

5:当用户提交时刻,会在redo buffer中记录提交信息,同时会在回滚段中标记该事务为非激活状态(inactive),这点很重要。

可以看到,在一个事务进行过程中,redo和undo是交替出现的,redo buffer会首先记录此事务变化前的数据和变化后的数据,然后把变化前的数据写入回滚段,最后才在数据缓冲区中修改数据。

以下把instance crash后,先forward,再open,再把未提交的rollback的详细过程介绍如下:

当以上这个语句执行到第四步的时候,正巧有某种原因导致oracle要flush buffer cache,比如buffer cache满了等等时间发生,此时,oracle要把脏数据写入磁盘,也就是此时触发了dbwr写进程,又由于dbwr写之前一定要触发lgwr,所以以上语句执行的前4步都会写入redo文件中。

此时,如果发生数据库崩溃,由于没有提交动作发生,也就是没有第五步的操作了 那么,在数据库回滚段中标记这个事务将仍为激活状态(active)。

在数据库重新启动过程中,后台进程SMON会扫描undo segment header,将发现上面的执行语句还是处于激活状态,于是, 将这些未提交的活动事务标志为dead。

roll forward可能发生在以下两种情况下:

(1):如果以上语句在执行第三步时,数据库crash,那么undo回滚段中记录的此事务的前镜像数据将丢失,数据库在启动过程中,会首先发生rollforward,根据redo文件记录的信息,在回滚段中生成name='old_exitgogo'的前镜像。这也是redo为什么记录undo信息的原因。

(2):如果以上语句提交后,dbwr进程还没有来的及将修改信息写到数据文件,此时数据库崩了,那么数据库在重新启动后也要进行roll forward,此时根据redo log文件的记录更新数据文件。也就是让以上语句的更改生效,所以只要提交的数据就不会丢失。

接下来数据库就可以open。

此后有两种情况下将发生回滚:

(1):后台进程SMON发现dead事务,根据情况去逐步回滚。

(2):由于数据库已经open,可能就有很多用户进程访问这些dead事务块。此时这些前台的进程将会去undo segment取得前镜像的数据,例如以上的name='old_exitgogo'这个值,然后修改数据缓冲区,完成回滚。这个过程本身也要产生redo,因此回退这个操作代价很大。

至此,数据库启动过程的前滚以及回退操作完成.

时间: 2024-09-20 14:56:37

Oracle前滚和Oracle后滚的学习案例的相关文章

Oracle误删除表数据后的数据恢复详解_oracle

Oracle误删除表数据后的恢复详解   测试环境: SYSTEM:IBM AIX 5L                         Oracle Version:10gR2   1. undo_retention参数的查询与修改 使用show parameter undo命令查看当前的数据库参数undo_retention设置. 显示如下: SQL> show parameter undo NAME                                 TYPE        V

Oracle Database 10g:回滚监视

oracle 为用户提供对回滚操作时间的准确评估 我们还在这地方吗?还要多长时间? 听起来熟悉吗?这些问题可能是您在前往孩子们最喜爱的主题公园的路上,从汽车后座上提出来的,并且经常是不断地.越来越频繁地提出来.您不想告诉他们还确切需要多长时间吗 - 或者更简单些,您自己知道答案吗? 同样,在回滚长期运行的事务时,经常会有些用户不停地询问相同的问题.这些问题是合理的,因为该事务进行了锁定,正常的处理经常受到回滚进程的影响. 在 Oracle 9i Database 及更低的版本中,您可以执行查询

Oracle 11g安装成功后在linux创建chkconfig自启动设置

本文参照了网上不同版本的资料,然后自己分别在cent0S6.3的x86与x64两个虚拟环境均搭建完成,安装的分别是与系统对应的ORACLE 11Gx86与x64两个版本,基本能满足Oracle服务开机启动需求. 但有几个小问题,能力有限: 1.启动或关闭服务报有此提示,但不影响服务启动,端口能正常打开,ORACLE远程也能连接. [root@orcl ~]# service oracle restart Shutdown Oracle: Environment variable ORACLE_U

数据库-oracle表空间修改后导出,然后导入修改好的表空间,导入失败,显示导入的表空间还是不存在!

问题描述 oracle表空间修改后导出,然后导入修改好的表空间,导入失败,显示导入的表空间还是不存在! 我原先的数据库的表空间是XMGL,然后我修改了一张表,将其表空间修改为了 WGP,然后导出,然后通过一台服务器,这台服务器的表空间就是 WGP,然后导入就报错 报错说是 XMGL不存在,问题是我原先导出前已经修改了表空间,导出还是原先的表空间,求解,数据库我也重启了,还是不行,求大神! 解决方案 参考Import: Tablespace does not exist tips 你的表里面有CL

在oracle中删除id后id就不再连续了

问题描述 如何在oracle中删除id后 再次让id连续比如我删除了id为1,3,5的数据后再次查询 id就不再试从1开始了,而是从2请教各位 如何做到 问题补充:redstarofsleep 写道 解决方案 id是一个唯一值,最好的处理方式就是一次写入永不更改.你的改动会带来级联效应,系统中所有涉及到这个表的外键都要更改.而你改动了这个值有什么好处呢?你这个改动就像一个城市的车牌因为其中一个号码报废了,所有的后续车牌都要递减一个号码一样.有意义么?解决方案二:明白你的意思了,你就是想让ID永远

服务-oracle监听关闭后无法启动了。

问题描述 oracle监听关闭后无法启动了. 我登录PL/SQL的时候提示无监听程序,我就把服务里面OracleOraDb10g_home1TNSListener关闭了,再启动就报错.网上一大堆乱七八糟的答案没一个有用的.有谁清楚怎么回事吗. 解决方案 监听文件有问题吧,怎么key=这打印出来的括号也没有匹配,看看listener.ora文件中写的格式是否有问题 解决方案二: 能不能直接把这个oracle服务给关闭了? 解决方案三: 如果你安装的是oracle完整版,可以用oracle自带的Ne

oracle删除表空间后重新创建相同名字的表空间出现错误ORA-01537

问题描述 oracle删除表空间后重新创建相同名字的表空间出现错误ORA-01537 如题所示,我在一开始删除表空间时没有使用drop tablespace ××× including contents and datafiles语句,导致dbf文件没有删除掉.导致现在dbf文件删不掉了,手动删除后,只要oracle服务已启动就会自动再创建一个同名的dbf文件.求解决方法. 解决方案 Oracle菜鸟之如何创建和删除表空间oracle 表空间,用户的创建及删除 解决方案二: 看一下你保存表空间的

c# net-c#.net 调用oracle存储过程,不能正常回滚

问题描述 c#.net 调用oracle存储过程,不能正常回滚 本人是个小菜,刚接触.net不久,使用事务不熟练,导致回滚失败.下面是代码: enter code here using (OracleConnection conn = new OracleConnection(strConn)) { if (conn.State != ConnectionState.Open) { conn.Open(); } OracleCommand cmd = conn.CreateCommand();

c#+oracle 11g-用C#,Oracle 11g 怎样建立数据库?怎样学习?

问题描述 用C#,Oracle 11g 怎样建立数据库?怎样学习? 怎样建立用C#建立以Oracle库为来源的数据库?从哪里入手?之前未接触过C#,对C++和C稍了解,但是都用的VC6.0,没用过VS2010,对Oracle不了解,求指导,怎样去完成数据库?学习的步骤怎样安排比较合理? 解决方案 买本ORACLE的教学书籍,安装好ORACLE客户端,多动手练习 解决方案二: http://www.jb51.net/article/37008.htm 先连接上.其余的就好办了