原子选择和更新

Álv*_*lez 5 php oracle oracle10g

如果我的数据如下所示:

ID STATUS     DATE_ADDED
== ========== ==========
 1 Processing 2011-04-01
 2 New        2011-04-02 
 3 New        2011-04-03
 4 Processing 2011-04-03
 5 Done       2011-04-06
 6 New        2011-04-06
 7 New        2011-04-14
 8 Done       2011-04-14
 ...
Run Code Online (Sandbox Code Playgroud)

...建议选择10条状态为“新”的最旧记录并将其状态设置为“正在处理”,同时确保任何其他并发进程不能对相同记录执行相同操作的推荐方法是什么?

这是一个在Windows Server 2003下以PHP / 5.2.6运行的Web应用程序,它通过ODBC(Oracle的驱动程序,而不是Microsoft的驱动程序)连接到远程Oracle 10g服务器。

Ada*_*sch 3

这在 Oracle 10g 中很难做到。在 11g 中,SELECT FOR UPDATE ... SKIP LOCKED语法使其变得简单。

一个简单的UPDATE语句就会序列化。正如将SELECT FOR UPDATE. 当然,两个竞争进程永远不会获得相同的行;问题是它们充其量只能串行化,而最坏的情况则可能导致死锁。

推荐的方法是使用 Oracle 高级队列(或您选择的队列实现)将要处理的 ID 排入队列,并允许队列实现管理值的争用。

--

SQL 可以工作,但如果第二个用户在某人锁定了该范围的情况下为相同的偏移量运行该 SQL,则会失败并显示 ORA-00054。可以通过将选择包装在循环中、捕获 ORA-00054 错误并使用它来增加偏移量来缓解这种情况。

select * from my_table
 where rowid in 
       (select row_id 
          from (select rowid as row_id, rownum as rn 
                  from mytable where some_condition 
                 order by deterministic_sort_order)
         where rn between :low_rn and :hi_rn
       )
 for update nowait;
Run Code Online (Sandbox Code Playgroud)

排序表达式需要是确定性的(简单地说,包括主键作为排序表达式的末尾)以防止冲突。