【发布时间】: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