2010-09-23 50 views
4

我有一个更新查询,每次只重新计算一行中的每列值。 由于这些更新查询发生在同一行,我已经看到更多的行级锁争用。在Oracle中,更新不锁定行的方式?

我在想也许一个解决方案是让后续更新只是抢先任何正在进行的更新。这可能吗? Oracle是否支持这种更新?

拼出想法全:

  1. 更新查询#1开始,在自己的事务
  2. 需要更新行X
  3. 获取锁定行X
  4. 更新查询# 2开始,在其自己的交易
  5. 块中,等待查询#1释放行X上的锁。

我的想法是,第5步可以简单地为:查询#1中止,查询#2继续。或者可以免去首先获取行级锁。

如果更新查询只更新给定行中的列的子集,我意识到这种逻辑会是灾难性的错误。但事实并非如此 - 每次都重新计算每一列。

+0

这似乎有点奇怪有在同一行上出现的这么多的更新。你确定某个其他进程是故意尝试更新该行吗?还是有某种锁升级正在进行?例如。手动表锁,选择更新而没有足够的选择性where子句,DDL,位图索引或未索引的外键。 – 2010-09-23 01:05:36

+0

我同意这看起来很奇怪。这是因为用户数量巨大吗?或者是其他事情发生? (“选择更新”是一个好的罪魁祸首。)如果这是某种“全面运行”,我可能会寻求另一种解决方案。就像为每个子组运行总计而不是整体一样,然后查询将总结而不是仅检索表中的单个行。 – user158017 2010-09-23 02:12:58

回答

5

我会问一个物理表是否是正确的机制,无论你在做什么。一个因素是如何处理交易。任何意思是“不要在交易期间锁定”的事情都会涉及交易问题。

有一对夫妇的非事务选项:

Global context值可能是有用的(取决于如果您是在RAC),以及如何在重新启动后处理的持久性。

另一种选择是DBMS_PIPE其中您将有一个后台进程维护该表,并且单独的会话将消息发送到该进程而不是直接更新该表。

Queuing是另一种想法。

如果你只需要需要减少记录被锁定的时间,autonomous transactions可能是答案

+0

12.2的任何简单解决方案?我需要按日期desc分配的表格行数以百计的机器人。谢谢 – Toolkit 2017-09-27 16:58:57

1

有可能做什么你问的相反,已经查询2失败,如果查询1正在使用SELECT FOR UPDATE和NOWAIT

或者,你可以尝试看看是否可以通过调整isolation level得到预期的效果,但我不建议这样做没有经过广泛的测试,因为你不知道什么敲,它可能有特效。

0

Oracle的UPDATE不支持任何锁定提示。

OraFAQ forum表明这种哈克解决方法:

DECLARE 
    x CHAR(1); 
BEGIN 
    SELECT 'x' INTO x 
    FROM tablea 
    WHERE -- your update condition 
    FOR UPDATE OF cola NOWAIT; 

    UPDATE tablea 
    SET cola = value 
    WHERE -- your update condition 
EXCEPTION 
    WHEN OTHERS THEN 
    NULL; -- handle the exception 
END;