分享

oracle restart:语句重新执行

 昵称10504424 2013-11-14
今天看了tom大师关于sql restart的博客,收益颇深。鉴于翻墙的繁琐和以后查阅的方便,将主要内容总结至此。大家也可以通过如下地址查看原博文及精彩点评(需要翻墙哦)。

http://tkyte./2005/08/something-different-part-i-of-iii.html

http://tkyte./2005/08/part-ii-seeing-restart.html

http://tkyte./2005/09/part-iii-why-is-restart-important-to.html

大家都知道oracle通过一致性读来防止阻塞并为查询提供结果。但是对于写或者说编辑操作,oracle是怎样处理的那?例如下面的语句:
update t set x=2 where y=5;
对于这样的语句,oracle首先会根据语句的运行起始时间T1和WHERE条件进行基于T1的一致性查询操作,找出y=5的所有记录,然后对这些记录进行更新操作。那么这里就存在一个问题,假设在T2时间,oracle修改到记录R,如果在T1和T2之间的时间段里,某个用户进程修改了记录R并进行了提交,此时oracle会做如何处理那?我们知道,读操作我们可以基于以往时间点构造一致性块,但是对于写操作,我们必须对当前块进行操作。


首先我们在表tab上创建触发器

session1:更新某记录,不提交 session2:更新相同记录,进程被阻塞 session2:session1提交后
从这里可以看出,如果更新R时,oracle发现R已经被修改过,那么oracle会重新执行update语句。

下面让我们修改一下触发器

session2:在session1提交后:
非常奇怪?这里update语句并没有重新执行
下面在来改变一下执行语句:
sesion1:
session2:
这里update语句再次重新执行。好,我们总结如下:
如果在update(delete没有测试,估计应该是相同的)语句的执行过程中,待操作记录发生了改变,并且被改变的列在where子句或者row触发器(after or before)的内部使用:old或者:new引用过,那么update语句会将之前的操作回滚并重新执行。这也是after触发器效率高于before触发器的一个原因,因为即便update重新执行,after触发器只执行一次,而befer触发器会执行两次。如果发生了restart,oracle会在第二次执行的过程中尝试使用select for update来进行操作,以避免发生再一次的restart。但是即便使用select for update ,依然有可能发生restart。


下面看一下restart产生的影响:
1:如果触发器维护plsql中的全局变量,那么全局变量可能是不准确的
2:任何utl_函数,例如UTL_FILE, UTL_HTTP, UTL_SMTP,可能会执行两次,因此这些函数时非事务性的,无法回滚
3:自治事务当然也会受影响而执行多次



    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多