在多个服务器上批量运行

时间:2011-06-14 11:48:51

标签: database oracle concurrency batch-file oracle10g

我有一个批处理应用程序,它只包含这些步骤。

  • 从update-flag列为空的表中选择所有记录
  • 处理所选信息
  • 将记录标记为已更新

我正在使用Oracle 10g,而我正在尝试的是能够同时在多个服务器上执行此应用程序。但是,我担心Oracle的锁机制。 当我在第一台服务器上运行的应用程序的第一个实例选择一条记录时,第二台服务器上运行的另一个实例不应该能够选择它。

出于这种目的,使用“select for update”是否合适?如果我使用“select for update skip locked”模式,应用程序的第二个实例是否会静默跳过先前由第一个实例锁定的记录并选择其他行?或者,它是否等到锁定的行被释放?

非常感谢任何建议和意见

2 个答案:

答案 0 :(得分:0)

我的同事罗布写了一篇关于这个Parallellism in a skip locked scenario 的好文章 是的,它有效,不,它不会帮助你。 FWIW:稍微更改算法,给更新标志赋值,增加数量以帮助处理新数据的选择进程,并在准备好时更新为NULL可能更聪明。这里的优势是双重

  1. 缩小索引大小
  2. 它使得并行性更容易实现,因为进程现在都可以选择“自己的”行。
  3. 我希望它有所帮助。

答案 1 :(得分:0)

我使用select for update skip locked并且工作正常。是的,以后的会话会静默跳过先前会话锁定的记录并选择/锁定其他行。确保并行处理会话没有修改其他常见数据,否则会陷入另一个瓶颈。

declare 
  my_limit constant number default 1000;
  cursor cRecords is
    select primary_key
    from processed_table t
    where t.update_flag is null
    for update skip locked;
  type t_cRecords is table of cRecords%rowtype;
  tRecords t_cRecords;
begin
  open cRecords;
  while true loop
    -- Select all the records from the table where the update-flag column is null
    fetch cRecords bulk collect into tRecords limit my_limit;
    -- Process the selected information
    -- ...
    -- Mark the record as updated
    forall i in tRecords.first..tRecords.last
      update processed_table
        set update_flag = 'PROCESSED'
      where primary_key = tRecords(i).primary_key;
    --
    exit when tRecords.count < my_limit;
  end loop;
end;

顺便说一句,我没有确认Parallellism in a skip locked scenario - 在我的网站上,使用rwijk的脚本,速度提高了4到1秒。