代码之家  ›  专栏  ›  技术社区  ›  Roy Tsabari

在具有多个会话的Oracle中从表中选择

  •  1
  • Roy Tsabari  · 技术社区  · 15 年前

    我有多个线程正在处理来自同一个表(实际上是一个队列)的行。

    我希望每一行只由一个线程处理。因此,我添加了一列“IsInProccess”,并在threads SELECT语句中添加了“WHERE IsInProccess=0”。

    问题是我有很多线程,很多时候会出现以下情况: 线 通过“选择更新”从表中选择并获取行号。 1. . 在将IsInProcess更改为1之前,线程 以相同的方式从表中选择并获取行编号 1. 1. A. 会话和线程

    我希望当从表中选择某个线程时,Oracle将返回未保存到其他打开会话的行。

    4 回复  |  直到 15 年前
        1
  •  1
  •   Gary Myers    15 年前

    如果您有11g,请查看 SKIP LOCKED

        2
  •  2
  •   Jeffrey Kemp    15 年前

    这是一个解决方案的示意图,我以前见过它被非常成功地使用过:

    1. 使用SELECT FOR UPDATE NOWAIT语法,这样,如果会话无法立即获得行上的锁,它将引发异常,而不是等待锁。异常处理程序可以等待几秒钟(例如,使用dbms_lock.sleep);整个块可以被包装在一个循环中,该循环在放弃之前重试一定次数。

    2. ROWNUM<=n 使查询一次只尝试获取一定数量的行(例如1);如果成功,则将行更新为“正在处理”。

    3. 如果会话在将行标记为“进程中”时失败,则另一个进程可以通过搜索任何具有SID/SERIAL#但在中未找到活动会话的行来“清理”标记为“进程中”的行 v$session .

        3
  •  2
  •   David Aldridge    15 年前

        4
  •  0
  •   DVK    15 年前

    一个解决方案:

    1. 您还需要担心“孤立”行-例如,线程拾取行,然后在未完成工作的情况下死亡。要解决这个问题,一个解决方案是有两列:“IsInProcess”和“StartprocessingTime”。

      isInProcess将有3个值:0(未处理)、1(已拾取)、2(已完成)。

      其中isInProcess=0或(isInProcess=1,StartprocessingTime<getdate()-超时)”。