【发布时间】:2013-05-16 15:26:10
【问题描述】:
我想用 MERGE 语句以指定的顺序插入行以避免死锁。否则可能会发生死锁,因为多个事务将使用重叠的键集调用此语句。请注意,此代码对重复值异常也很敏感,但我通过重试来处理它,所以这不是我的问题。我正在执行以下操作:
MERGE INTO targetTable
USING (
SELECT ...
FROM sourceCollection
ORDER BY <desiredUpdateOrder>
)
WHEN MATCHED THEN
UPDATE ...
WHEN NOT MATCHED THEN
INSERT ...
现在我仍然遇到死锁,所以我不确定 oracle 是否维护子查询的顺序。在这种情况下,有谁知道如何最好地确保 oracle 以相同的顺序锁定 targetTable 中的行?我必须在合并之前执行 SELECT FOR UPDATE 吗? SELECT FOR UPDATE 以什么顺序锁定行? Oracle UPDATE 语句有一个 MERGE 似乎缺少的 ORDER BY 子句。除了每次都以相同的顺序锁定行之外,还有其他方法可以避免死锁吗?
[编辑] 此查询用于维护某个操作发生频率的计数。当操作在第一次插入行时发生时,当它发生第二次时,“count”列会增加。有数百万种不同的动作,它们经常发生。表锁不起作用。
【问题讨论】:
-
您可以尝试通过合并到 SELECT 中来按您的需要对目标表进行排序,例如:
MERGE INTO (SELECT * FROM targetTable ORDER BY <desiredUpdateOrder>) USING ...。不确定这是否会解决您的问题,但可能值得一试。分享和享受。 -
性能是否关键(尤其是响应时间)?如果没有,您是否考虑过序列化代码(在运行合并之前获取应用程序锁,然后在提交时释放)?
-
@JeffreyKemp 应用程序外观不起作用,请参阅编辑。
-
目标表的维护是否必须与更改同步,或者是否可以延迟?您是否考虑过使用物化视图来存储这些信息?
-
在这种情况下为 MV 方法 +1