【问题标题】:FOR UPDATE SKIP LOCKED with ROWNUM on ORACLE 12c在 ORACLE 12c 上使用 ROWNUM 锁定更新跳过
【发布时间】:2018-08-31 19:31:48
【问题描述】:

我搜索了所有论坛,但没有找到任何线索。 我有一个多个线程消耗的临时表。 为了避免死锁,我正在使用这样的东西:

SELECT ID_MESSAGE
FROM TB_STAGE_IN S 
WHERE S.CD_STATUS = 0 
AND S.ID_JOB_SCHEDULE IS NULL 
AND ROWNUM <= 10000 
FOR UPDATE SKIP LOCKED; 

它工作正常,但线程没有达到 10,000 行的最大值。 就像:

  • 线程 1:5000
  • 线程 2:3000
  • 线程 2:2000

我知道会发生这种情况,因为它们的行号是相同的,但表有成千上万行。我真正需要的是线程在每一步解锁 10,000 行。

我尝试仅使用 FETCH FIRST 10000 ROWS,但收到以下消息: ORA-02014: 无法从具有 DISTINCT、GROUP BY 等的视图中选择 FOR UPDATE。

大家可以帮帮我吗?

谢谢你的好意。

【问题讨论】:

  • SKIP LOCKED 发生在 WHERE 子句之后。因此,您的查询会找到 10,000 行,然后返回这 10,000 行中未锁定的子集。
  • 这就是为什么三个线程每个都不能得到 10k 行的原因。我想要的是在每个线程上获得 10k。该表本身包含超过一百万行。
  • DBMS_PARALLEL_EXECUTE 会将您的表分块并执行多个工作人员来处理这些块。听起来你正试图重新发明它。如果你坚持在这里滚动你自己的设计,那么没有什么神奇的 Oracle 方法可以做你想做的事。相反,您将需要每个工作人员写入并提交(可能在自治 txn 中)它已抓取以进行处理的行。这样,每个工作人员都可以抓取尚未分配的行。由于您正在提交数据,因此您需要确保工作人员在不删除那些“锁定”指标的情况下不会失败。
  • 我会学习这个的,谢谢你的澄清。
  • 作业每次准确抓取 10000 行是否重要?如果您有投票工作,他们会抓住一些闲置的任务,推进它们,而不是再去抓另一把闲置的任务。问题是你有一个固定的步骤开销,你需要最小化它的执行次数吗?

标签: sql multithreading oracle


【解决方案1】:

问汤姆有一个像这样的suggestion

open C;  -- cursor C is select ... for update skip locked;

loop
  fetch C bulk collect into :my_array limit 100;
  append :my_array to :to_be_processed_array;
  exit when c%notfound or :to_be_processed_array.count >= 10000;
end loop;

-- process any rows in :to_be_processed_array

close C;

【讨论】:

  • 是的!在 Ask Tom 论坛上进行了一番交谈后,我使用了这种方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-02-20
  • 1970-01-01
  • 1970-01-01
  • 2020-07-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多