设为首页 收藏本站
查看: 756|回复: 0

[经验分享] Oracle前滚和回滚

[复制链接]

尚未签到

发表于 2018-9-13 12:23:48 | 显示全部楼层 |阅读模式
  案例(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中。
  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,因此回退这个操作代价很大。
  至此,数据库启动过程的前滚以及回退操作完成.
  oracle视频教程请关注:http://down.51cto.com/4202939/up


运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-578119-1-1.html 上篇帖子: oracle技术之group by rollup查询结构 下篇帖子: Oracle Commit-Oracle之路
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表