试图了解ORA-00060和ORA-01555

时间:2015-12-07 22:39:16

标签: oracle deadlock undo-redo

我有两个表,表A和表B.

事务T1(自动提交设置为false)  更新表A,  读表B和  再次更新表A.  然后提交。

交易2  删除表B和  有一个后触发器来删除表A中的相关记录。

事务1和事务2从不同的应用程序运行(即并行运行)

现在我的条件是交易T1和T2在表A上被锁定(ORA-00060)。

在死锁错误之前,我发现在尝试读取表B时,事务1遇到了ORA-01555(这是它的第二步)。

现在我很困惑,交易T1和T2是否有可能在正常情况下相互死锁,或者ORA-01555是否可以在死锁中发挥作用。

任何帮助都将不胜感激。

1 个答案:

答案 0 :(得分:1)

我怀疑ORA-1555与死锁有什么关系,除非它在您的代码中触发创建额外锁的异常处理程序。

实际上,表B可能与情况无关,因为事务T1没有锁定它。 (我在解读“读表B” 表示“从表B中选择”而不是“从表B中选择进行更新”。)

我从ORA-1555得到的结论是,从B读取T1需要很长时间,这意味着T2有足够的时间尝试获取T1所持有的A上的锁定,这样,当T1继续并且尝试获取T2在开始等待之前获得的锁定,将发生死锁。

听起来你有一些严肃的应用程序设计问题。 T1长时间锁定其他会话所需的记录。即使您解决了死锁问题,您的应用程序也会遇到可扩展性问题。

我知道避免死锁问题的最佳方法是确保锁定资源的所有事务以相同的顺序锁定它们。

这是死锁的秘诀:

  1. T1 ==>锁定记录#1
  2. T2 ==>锁定记录#2
  3. T2 ==>尝试锁定记录#1(等待T1)
  4. T1 ==>尝试锁定记录#2 ==>僵局!
  5. 如果按照您的应用程序的设计,强制T1和T2以相同的顺序工作,那么它应该是:

    1. T1 ==>锁定记录#1
    2. T2 ==>锁定记录#1(等待T1)
    3. T1 ==>锁定记录#2
    4. T1 ==>提交或回滚
    5. T2 ==> (继续)锁定记录#2 ==>没有死锁!
    6. 虽然正如我所指出的那样,你的设计仍然无法扩展,因为T2花了很多时间等待。这是一个更难的问题。

      旁注:在上面的示例中,T1必须提交或回滚 - 根据时间安排,回滚到保存点可能还不够,因为,在Oracle数据库中,回滚到保存点的T1将会释放锁定记录#1但它不会告诉事务T2它可以继续。