Oracle 死锁在同一条记录上不断重复

Oracle deadlock keeps repeating on the same record

我对以下查询有疑问:

SELECT o.OID, o.DOSSIER_KEY, o.DOSSIER_TYPE 
FROM TVM04_VMAX_TEMP_RIGHTS      
WHERE o.DOSSIER_KEY = ? 
AND o.DOSSIER_TYPE = ? FOR UPDATE

即使它以不同的时间间隔重复多次,它仍然会导致死锁。如果我了解死锁是如何发生的,我希望两个冲突会话中的一个回滚,另一个继续前进 (here)

我确实得到了 内部异常:java.sql.SQLException:ORA-00060:在等待资源时检测到死锁,但是在我们的系统上另一个 tx 再次访问相同记录的可能性,每次我 运行 手动查询,在我看来接近于 0。

这是我的转储 Oracle 文件:

Deadlock graph:
                   ---------Blocker(s)--------  ---------Waiter(s)---------
Resource Name          process session holds waits  process session holds      waits
TX-00400007-008c00ec       304     786     X            300     757           X
TX-00070016-0002dae6       300     757     X            304     786           X

session 786: DID 0001-0130-011DAD37     session 757: DID 0001-012C-00B1E41F 
session 757: DID 0001-012C-00B1E41F     session 786: DID 0001-0130-011DAD37 

Rows waited on:
Session 786: obj - rowid = 0003921D - AAA5IdAAMAAHjdyAAG
(dictionary objn - 234013, file - 12, block - 1980274, slot - 6)
Session 757: obj - rowid = 0003921D - AAA5IdAARAACfC6AAz
(dictionary objn - 234013, file - 17, block - 651450, slot - 51)

----- Information for the OTHER waiting sessions -----
Session 757:
sid: 757 ser: 387 audsid: 18983600 user: 64/WLSP01
flags: (0x41) USR/- flags_idl: (0x1) BSY/-/-/-/-/-
flags2: (0x40009) -/-/INC
pid: 300 O/S info: user: oracle, term: UNKNOWN, ospid: 42730046
image: oracle@H50A450
client details:
O/S info: user: weblogic, term: unknown, ospid: 1234
machine: H53AD20 program: JDBC Thin Client
application name: JDBC Thin Client, hash value=2546894660
current SQL:
SELECT o.OID, o.DOSSIER_KEY, o.DOSSIER_TYPE FROM TVM04_VMAX_TEMP_RIGHTS     o    WHERE o.DOSSIER_KEY = :1  AND o.DOSSIER_TY
PE = :2  FOR UPDATE

----- End of information for the OTHER waiting sessions -----

Information for THIS session:

----- Current SQL Statement for this session (sql_id=489bnqugb9wsz) -----
SELECT o.OID, o.DOSSIER_KEY, o.DOSSIER_TYPE FROM TVM04_VMAX_TEMP_RIGHTS o    WHERE o.DOSSIER_KEY = :1  AND o.DOSSIER_TYPE
 = :2  FOR UPDATE
===================================================

你有什么提示为什么会发生以及如何发生吗?

非常感谢您!

法比奥

我建议使用 SKIP LOCKED 子句来避免其他会话获取已锁定的行进行更新。

它只会锁定它可以select更新的行,其余被跳过的行已经被其他会话锁定。

例如,

会话 1:

SQL> SELECT empno, deptno
  2    FROM emp  WHERE
  3   deptno = 10
  4  FOR UPDATE NOWAIT;

     EMPNO     DEPTNO
---------- ----------
      7782         10
      7839         10
      7934         10

SQL>

第 2 节:

SQL> SELECT empno, deptno
  2    FROM emp  WHERE
  3   deptno in (10, 20)
  4  FOR UPDATE NOWAIT;
  FROM emp  WHERE
       *
ERROR at line 2:
ORA-00054: resource busy and acquire with NOWAIT specified or timeout expired

现在让我们跳过会话 1 锁定的行

SQL> SELECT empno, deptno
  2    FROM emp  WHERE
  3   deptno IN (10, 20)
  4  FOR UPDATE SKIP LOCKED;

     EMPNO     DEPTNO
---------- ----------
      7369         20
      7566         20
      7788         20
      7876         20
      7902         20

SQL>

因此,department = 10 会话 1 锁定,然后 department = 20 会话 2 锁定。

另外,看看我的回答here for better understanding of deadlocks. Please read Understanding Oracle Deadlock