在Oracle中,更新不锁定行的方法是什么?

时间:2010-09-23 00:39:40

标签: sql oracle

我有一个Update查询,每次都会在一行中重新计算-every-列值。 由于这些Update查询发生在同一行,我一直看到更多的行级锁争用。

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

完整地阐明这个想法:

  1. 更新查询#1在其自己的事务中开始
  2. 需要更新第X行
  3. 获取第X行的锁定
  4. 更新查询#2在其自己的事务中再次开始
  5. 阻止,等待查询#1释放第X行的锁。
  6. 我的想法是,第5步可以简单地说:查询#1中止,查询#2继续。或者可以免除首先获得行级锁定。

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

3 个答案:

答案 0 :(得分:5)

我会问一个物理表是否适合你正在做的事情。一个因素是如何处理交易。任何意味着“不要在交易期间锁定”的任何事情都会遇到交易问题。

有几种非交易选项:

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

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

Queuing是另一种想法。

如果您只需要缩短锁定记录的时间,autonomous transactions可能就是答案

答案 1 :(得分:1)

可以执行您所询问的相反,如果使用SELECT FOR UPDATE和NOWAIT查询1正在进行中,则查询2将失败。

或者,您可以尝试通过调整isolation level来查看是否可以获得所需效果,但我不建议在没有进行大量测试的情况下进行此操作,因为您不知道它可能具有什么连锁效应

答案 2 :(得分: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;