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

标签 oracle plsql database-deadlocks

我有下面的过程,其中有 pragmaautonomous_transaction 子句。现在在验证业务逻辑后,在 Java 代码中调用该过程。执行此过程后,它会以一些 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 个触发器用于插入,2 个触发器用于更新前事件。

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

我收到以下错误。

ORA-00060: deadlock detected while waiting for resource

ORA-06512: at "ADTTRG_xyz", line 277

ORA-04088: error during execution of trigger 'ADTTRG_xyz'

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

请解释为什么会出现这种死锁。

最佳答案

"How deadlock is occurring."

当两个 session 同时尝试更改公共(public)资源(例如表或唯一索引)时,就会发生死锁,而在没有另一个 session 先提交的情况下,两个 session 都无法提交。这始终是一个应用程序设计缺陷,因为死锁是复杂流程和实现不当的逻辑策略的结果。

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

ORA-06512: at "ADTTRG_xyz", line 277

首先,具有数百行代码的触发器是一种代码味道。触发器中有很多代码。看来那里有竞争的机会。尤其是作为...

Table 'xyz' has three triggers and ... 2 are on Before update event.

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

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

pragma autonomous_transaction;

PL/SQL documentation说“如果自治事务尝试访问主事务持有的资源,则可能会发生死锁。”自治事务是另一种代码味道。自主交易的有效用例很少;更常见的是,它们被用来说服错误的数据模型提交。

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

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

一旦您知道哪个表处于死锁状态,您就知道必须在应用程序逻辑中更改哪些内容。这可能是一个相当大的变化,因为您的代码有许多危险信号(长触发器主体、同一事件上的两个触发器、自主事务)。祝你好运!

关于oracle - 由于 Pragma 自治事务过程检测到死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47862122/

相关文章:

Java 甲骨文事务

c# - 将数组参数从 C# 传递到表的 Oracle 集合类型

regex - PL/SQL 优化在 varchar 中搜索日期

sql-server - 没有事务的 Azure SQL 数据库上的死锁

选择更新甚至排序之间的 PostgreSQL 死锁

oracle - Oracle 中的经纬度距离计算查询

c# - 从 C# 调用 Oracle 中的存储过程

oracle - 格式化存储过程

sql - 如何在绑定(bind)变量中传递空值