我有一个包含多个线程要处理的100个条目的列表。每个线程最多需要处理20个条目。
我目前正在使用全局临时表来存储符合特定条件的条目 - 我也不希望线程重叠要处理的条目。
我该怎么做(防止重叠)?
谢谢!
答案 0 :(得分:5)
如果是11g,我会使用SELECT ... FOR UPDATE SKIP LOCKED
。
如果在以前的版本中,我将使用高级队列来填充具有要处理的条目的主键值的队列,并让您的线程将这些键出列以处理这些记录。因为在处理事务范围内,dequeue可以(但不一定是,如果内存服务),dequeue会提交或回滚处理,并且没有两个线程可以获得相同的记录来处理。
答案 1 :(得分:2)
这里有两个问题,让我们分别处理它们:
您可以使用高级排队或跳过锁定功能suggested by Adam。
您还可以使用包含处理信息的列,例如未处理时为空的STATE列。每个线程都会在以下行开始工作:
UPDATE your_table
SET state='P'
WHERE STATE IS NULL
AND rownum = 1
RETURNING id INTO :id;
此时线程将提交以防止其他线程被锁定。然后你会进行处理,并在完成后选择另一行。
或者,您也可以事先拆分工作,并为每个流程分配一系列需要处理的ID。
每个线程最有可能拥有自己的Oracle会话(否则您无法并行运行查询)。这意味着每个线程都有自己的临时表的虚拟副本。如果您事先在此表中存储了数据,则线程将无法看到它(临时表在会话开始时将始终为空)。
如果要存储多个会话可访问的数据,则需要常规表。临时表适用于存储单个会话专用的数据,例如复杂过程中的中间数据。
答案 2 :(得分:0)
最简单的方法是使用DBMS_SCHEDULER为您要处理的每一行安排作业。您必须将密钥传递给永久表以标识要处理的行,或将完整行放入作业的参数中,因为临时表的内容在不同的会话中不可见。并发作业的数量由资源管理器控制,大多数受cpus数量的限制。
为什么要逐行处理?在大多数情况下,集合操作要快得多。