1

我有两个 Oracle 查询在不同的会话中运行,它们处于死锁状态,我无法理解为什么会发生这种情况。

会话 1 中的查询是这样的:

UPDATE REFS R SET R.REFS_NAME = :B2 WHERE R.REFS_CODE = :B1 

会话 2 中的查询是这样的:

UPDATE REFS R SET R.STATUS_CODE = :B3, R.STATUS_TYPE = :B2 WHERE R.REFS_CODE = :B1 

每个都被一个游标包围,该游标循环选择主键值。当这些查询同时运行时,它们就会死锁。REFS_CODE 是主键,Oracle 跟踪显示它们正在更新不同的 rowid。显然,主键是索引的,并且有一些外键约束,索引支持这些约束,因为这在过去对我们来说一直是个问题。

进入绝望的领域,我尝试禁用桌面上的触发器,但没有帮助。还尝试使用自主事务,但这使事情变得更糟。

有什么我想念的吗?谢谢你的帮助!

4

1 回答 1

3

如果在更新整个游标批次之后发生提交,那么它可能只是一个直接的死锁场景,其中两个游标在相同的行上以不同的顺序操作。

  • 假设在尝试提交之前session 1已经并且cursor set 1正在按该顺序更新。refs_code 1refs_code 2
  • 假设在尝试提交之前session 2已经并且cursor set 2正在按该顺序更新。refs_code 2refs_code 1

然后,交错更新:

time  cursor set 1    cursor set 2
====  ============    ============

t1    refs_code 1     -
t2    -               refs_code 2
t3    refs_code 2     -
t4    -               refs_code 1

在 t3,cursor set 1正在等待cursor set 2提交refs_code 2 在 t4,cursor set 2正在等待cursor set 1提交refs_code 1

这两个事务正在等待不同的 rowid。如果是这种情况,您可以order by向两个光标添加(在同一方向上)以帮助避免这种情况。

于 2013-04-26T01:28:21.893 回答