全局临时表 - 锁定行+并发问题

时间:2011-05-06 05:06:53

标签: sql oracle

我有一个包含多个线程要处理的100个条目的列表。每个线程最多需要处理20个条目。

我目前正在使用全局临时表来存储符合特定条件的条目 - 我也不希望线程重叠要处理的条目。

我该怎么做(防止重叠)?

谢谢!

3 个答案:

答案 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数量的限制。

为什么要逐行处理?在大多数情况下,集合操作要快得多。