为什么这些查询陷入僵局?

时间:2013-04-25 22:05:47

标签: oracle database-deadlocks

我在不同的会话中运行了两个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。显然,主键是索引的,并且有一些外键约束,索引支持这些约束,因为这对我们来说是一个问题。

进入绝望的境界,我已经尝试禁用桌面上的触发器,但这没有用。还尝试使用自治事务,但这使事情变得更糟。

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

1 个答案:

答案 0 :(得分:3)

如果在更新整个游标批处理后发生提交,那么它可能只是一个直接的死锁情况,其中两个游标在相同的行上运行,但顺序不同。

  • 假设session 1cursor set 1,并且在尝试提交之前按顺序更新refs_code 1refs_code 2
  • 假设session 2cursor 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(朝同一方向),以帮助避免这种情况。