从同一个表中读取10多个进程的生产者 - 消费者

时间:2013-11-13 13:37:44

标签: oracle parallel-processing oracle11gr2

我有这样的表格FIDDLE

CREATE TABLE buffor_table
    ("ID" int, "NAME" varchar2(10), "STATUS" varchar2(10))
;

INSERT ALL 
    INTO buffor_table ("ID", "NAME", "STATUS")
         VALUES (1, 'something1', 'PROCESSING')
    INTO buffor_table ("ID", "NAME", "STATUS")
         VALUES (2, 'something2', 'WAITING')
    INTO buffor_table ("ID", "NAME", "STATUS")
         VALUES (3, 'something3', 'WAITING')
    INTO buffor_table ("ID", "NAME", "STATUS")
         VALUES (4, 'something4', 'FINISHED')
SELECT * FROM dual
;

CREATE OR REPLACE VIEW V_BUFFOR_WAITING AS
  SELECT ID, NAME, STATUS FROM BUFFOR_TABLE
  WHERE STATUS = 'WAITING';

我需要有一些流程/工作,每分钟都会在“WAITING”状态下查找行,然后为每一个跨越新的子流程来完成工作。

我想提供这个解决方案;创建10个链(使用Oracle链)并将它们设置为执行并行,并且每分钟都会启动oracle作业。 Chain逻辑很简单:

  1. select id into id_to_process from v_buffor_waiting where rownum < 2 for update;
  2. update buffor_table set status='PROCESSING' where id = id_to_process;
  3. commit
  4. 做一些长时间的计算等
  5. 用于将状态设置为FINISHED
  6. 的简单更新/提交操作

    我知道{1}}异常可以在第1位抛出。它将被视为“无所事事”。

    我的步骤1-3仅用于锁定一行(当启动10个并行链时我希望每个链只处理一行)而步骤1-3将像原子操作一样 - 其他进程没有相同的ID处理。

    这个问题有标准方法吗?

1 个答案:

答案 0 :(得分:1)

这是典型的调度方案。 Oracle非常擅长并行运行SQL查询和更新,但这可能更难。我过去曾使用Oracle作为后端在三个不同的调度程序上工作。

根据我的经验提出的一些建议:

  • 使用表格,而不是视图,因为视图没有锁定触发器(你已经做好了)。
  • 使用'更新'并超时以避免永久锁定。
  • 请记住,多处理器系统中的Oracle使用旋转而不是休眠来获取数据库锁。
  • 通过确保所有并发进程遵循相同的顺序来避免'用餐菲利斯'问题。这可以避免死锁。
  • 每次尝试获取锁定后添加睡眠。
  • 确保在事件(例如数据库关闭)之后释放锁。例如,通过在update语句中注册buffor_table中的sid / serial#。并自动释放锁。
  • 确保在链条崩溃后释放锁定。类似地,使用sid / serial#或类似的东西来检测消费过程是否仍然存在。
  • 作为替代方案,请查看dbms_lock。它有一些限制,但可能提供更简单但不太灵活的解决方案。

我希望这能回答你的问题。如果没有,请延长您的问题或让我知道您遗失的内容。