由于Pragma自治事务过程检测到死锁

问题描述 投票:1回答:1

我有以下过程,其中包含pragma autonomous_transaction子句。现在,在验证来的业务逻辑之后,在Java代码中调用此过程。在执行了这个proc之后,它从一些java东西开始......

create or replace procedure UPDATE_INSTRUMENT 
is
  pragma autonomous_transaction;

begin

  begin
    update abc
       set AUTHSTATUS   = p_AUTHSTATUS,
           STATUS       = p_STATUS,
           USERID       = p_USERID,
           LASTUPDATED  = TO_DATE(p_LASTUPDATED, 'DD/MM/YYYY'),
           USERDATETIME = TO_DATE(p_USERDATETIME, 'DD/MM/YYYY')
    where  TRANSACNO = p_TRANSACNO;
    commit;
  end;

  begin
    update xyz
       set AUTHSTATUS = p_AUTHSTATUS,
           USERID      = p_USERID,
           AUTHDATE    = TO_DATE(SYSDATE, 'DD/MM/YYYY'),
           LASTUPDATED = TO_DATE(SYSDATE, 'DD/MM/YYYY'),
    where  TRANSACNO = p_TRANSACNO;
    commit;
  end;

end UPDATE_INSTRUMENT;

表'xyz'有三个触发器,其中1个在Insert上,2个在Before更新事件之前。

P.N: - 在调用此过程之前,表'xyz'未在任何地方更新或锁定。

我收到以下错误。

ORA-00060:等待资源时检测到死锁

ORA-06512:在“ADTTRG_xyz”,第277行

ORA-04088:执行触发器'ADTTRG_xyz'时出错

表abc正在正确更新,但无法更新表xyz。

请解释为什么会出现这种僵局。

oracle plsql database-deadlocks
1个回答
2
投票

“发生了多么僵局。”

当两个会话同时尝试更改公共资源(例如表或唯一索引)时,会发生死锁,这样两个会话都可以在没有其他提交的情况下提交。这始终是一个应用程序设计缺陷,因为死锁是复杂流程和执行不当的逻辑策略的结果。

这里有一些线索就是这种情况。

ORA-06512:在“ADTTRG_xyz”,第277行

首先,具有数百行代码的触发器是代码气味。这是触发器中的大量代码。似乎那里有竞争的机会。特别是......

表'xyz'有三个触发器,而... 2在更新前事件。

'xyz'表上有两个BEFORE UPDATE触发器,生成死锁的事件是'xyz'的更新。这可能不是巧合。

您必须调查这两个触发器并确定它们需要哪些表和索引,以便您可以发现它们是否处于争用状态。

pragma autonomous_transaction;

PL/SQL documentation说“如果一个自治事务试图访问主事务所持有的资源,就会发生死锁。”自治交易是另一种代码味道。自治交易的有效用例非常少;更常见的是,他们习惯于将糟糕的数据模型与提交内容纠缠在一起。

所以你有很多事情需要调查。 Oracle提供诊断来帮助解决此问题。

发生死锁时,Oracle会生成跟踪文件。该文件将写入OS目录。如果您不知道它在哪里,您可以查询V $ DIAG_INFO视图。 Find out more。跟踪文件将告诉您生成死锁的两个rowid;你可以使用dbms_rowid.rowid_object()找出对象id并将其插入select object_name from all_objects where object_id = :oid;。根据组织安排事项的方式,您可能无法访问tracefile目录,在这种情况下,您需要向DBA寻求帮助。

一旦你知道哪个表处于死锁状态,你就会知道你的应用程序逻辑中必须要改变什么。可能这是一个相当大的变化,因为你的代码有许多红色标志(长触发器体,同一事件上的两个触发器,自治事务)。祝好运!

© www.soinside.com 2019 - 2024. All rights reserved.