代码之家  ›  专栏  ›  技术社区  ›  Aaron Fi

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

  •  4
  • Aaron Fi  · 技术社区  · 14 年前

    我有一个更新查询,每次只在一行中重新计算每列的值。 由于这些更新查询发生在同一行上,我看到了更多的行级锁争用。

    我在想一个解决方案可能是让后续的更新简单地先于已经在进行中的任何更新。这有可能吗?Oracle是否支持这种更新?

    完整地阐明这个想法:

    1. 更新查询1在其自己的事务中开始
    2. 需要更新第X行
    3. 获取第x行的锁
    4. 更新查询2在其自己的事务中再次开始
    5. 块,等待查询1释放第X行的锁。

    我的想法是,步骤5可以简单地是:查询1被中止,查询2继续。或者可能不需要首先获取行级锁。

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

    3 回复  |  直到 10 年前
        1
  •  5
  •   Gary Myers    14 年前

    我会问物理桌是否是你做任何事情的正确机制。一个因素是如何处理事务。任何表示“在事务期间不锁定”的内容都会遇到事务问题。

    有几个非事务性选项:

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

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

    Queuing 是另一个想法。

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

        2
  •  1
  •   Gaius    14 年前

    可以这样做 相反的 如果查询1正在使用select for update和 NOWAIT .

    或者,您可以尝试通过调整 isolation level 但是我不建议没有广泛的测试就这样做,因为你不知道它可能会有什么连锁反应。

        3
  •  0
  •   Vadzim    10 年前

    甲骨文的 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;