1

我收到了以下 oracle 日志:

DEADLOCK DETECTED ( ORA-00060 )

[Transaction Deadlock]

The following deadlock is not an ORACLE error. It is a
deadlock due to user error in the design of an application
or from issuing incorrect ad-hoc SQL. The following
information may aid in determining the deadlock:

Deadlock graph:
                       ---------Blocker(s)--------  ---------Waiter(s)---------
Resource Name          process session holds waits  process session holds waits
TX-00120007-0002acbf        82     185     X             67     240           X
TX-0008001c-0009ed94        67     240     X             82     185           X

session 185: DID 0001-0052-00000004 session 240: DID 0001-0043-00000004 
session 240: DID 0001-0043-00000004 session 185: DID 0001-0052-00000004 

Rows waited on:
  Session 185: obj - rowid = 0001285C - AAAShcAAiAAEoVFAAi
  (dictionary objn - 75868, file - 34, block - 1213765, slot - 34)
  Session 240: obj - rowid = 0001285C - AAAShcAAiAAEoRWAA3
  (dictionary objn - 75868, file - 34, block - 1213526, slot - 55)

----- Information for the OTHER waiting sessions -----
Session 240:
  sid: 240 ser: 7 audsid: 32762787 user: 76/NETCRACKER1
    flags: (0x8000041) USR/- flags_idl: (0x1) BSY/-/-/-/-/-
    flags2: (0x40008) -/-
  pid: 67 O/S info: user: oracle, term: UNKNOWN, ospid: 26869908
    image: oracle@opipodb1
  client details:
    O/S info: user: adipoas1, term: unknown, ospid: 1234
    machine: opipoas1 program: JDBC Thin Client
    application name: JDBC Thin Client, hash value=2546894660
  current SQL:
  select o.object_id
  from nc_objects o,
       (select object_id
          from nc_objects
        connect by prior object_id = parent_id
         start with object_id = :a1
        union
        select object_id
          from nc_references
         where reference in (select object_id
                               from nc_objects
                             connect by prior object_id = parent_id
                              start with object_id = :a1)) ids
 where o.object_id = ids.object_id
 order by o.object_id
   for update of o.object_id

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

Information for THIS session:

----- Current SQL Statement for this session (sql_id=3mxkkzhttwa2q) -----
select o.object_id
  from nc_objects o,
       (select object_id
          from nc_objects
        connect by prior object_id = parent_id
         start with object_id = :a1
        union
        select object_id
          from nc_references
         where reference in (select object_id
                               from nc_objects
                             connect by prior object_id = parent_id
                              start with object_id = :a1)) ids
 where o.object_id = ids.object_id
 order by o.object_id
   for update of o.object_id
===================================================

这是否意味着两个相等的查询(但可能使用不同的数据)已相互锁定?

如果是这样,怎么会发生?- 这个查询锁定有序序列,我想我们这里不能有死锁。

DB 是元模型 object_id - PK

谢谢

4

1 回答 1

4

ORDER BY 不会总是防止死锁

这是导致查询死锁的可能情况:

  1. 会话 1 运行您的查询:id=A
  2. 会话 2 运行您的查询:id=B
  3. 会话 1 运行您的查询:id=B,会话 1 现在正在等待会话 2
  4. 会话 2 运行您的查询:id=A,发出死锁

当您发出时SELECT FOR UPDATE,您冒着等待另一个会话的风险。如果此会话已经在等待您,则存在死锁。

在 OLTP 环境中避免死锁的一种常见方法是仅发出SELECT FOR UPDATE NOWAIT. 让第二个会话失败而不是等待。


更新以下评论

您有多个会话更新同一个表。你有机会互相阻挡。如果您让他们等待并且他们更新了不止一行,您就有可能出现死锁。你有很多选择来管理这个:

  1. 让会话陷入僵局。Oracle 将自动检测到这一点并回滚。Oracle 只会回滚其中一个会话的最后一条语句,而不是整个事务,这意味着收到错误的会话应该先回滚,然后再重试。

  2. 按照我的建议,用 NOWAIT 运行它们。
    如果你不想让他们失败,你可以:

    1. 用 NOWAIT 锁定行
    2. 如果 ORA-56回滚
    3. 睡眠后(X 秒)从事务开始重试。

    您需要回滚以确保两个会话不会无限期地相互阻止。

  3. 序列化更新。这通常是通过确保只有一个会话可以同时更新表(或一系列行)来完成的。
    例如,您可以让所有会话在事务表中插入,并让单个作业将修改合并到最终表中。并发会话不能互相阻止。这显然会推迟对主表的更新(至少在提交之后)。

我不会建议选项 1,因为您无法控制死锁检测(因此您无法优化它)。

于 2013-02-07T16:12:27.690 回答