我在不同的会话中运行了两个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。显然,主键是索引的,并且有一些外键约束,索引支持这些约束,因为这对我们来说是一个问题。
进入绝望的境界,我已经尝试禁用桌面上的触发器,但这没有用。还尝试使用自治事务,但这使事情变得更糟。
有什么我想念的吗?谢谢你的帮助!
答案 0 :(得分:3)
如果在更新整个游标批处理后发生提交,那么它可能只是一个直接的死锁情况,其中两个游标在相同的行上运行,但顺序不同。
session 1
有cursor set 1
,并且在尝试提交之前按顺序更新refs_code 1
和refs_code 2
。session 2
有cursor set 2
,并且在尝试提交之前按顺序更新refs_code 2
和refs_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
(朝同一方向),以帮助避免这种情况。