选择更新已跳过锁定行限制

时间:2013-04-30 12:14:41

标签: java oracle queue batch-processing

我有一个用Java编写的程序,它创建了5个从Oracle中选择数据的线程。 选择是这样的:

select * from queue_requests where request_status = 0 and date_requested <= sysdate and rownum <= ? for update skip locked

我将参数设置为1024.我经常得到以下结果(使用System.out.println):

  

THREAD 0 UPDATE 1024

     

THREAD 4 UPDATE 0

     

THREAD 1 UPDATE 0

     

THREAD 2 UPDATE 0

     

THREAD 3 UPDATE 0

因此,只有一个线程找到要更新的行。 根据我在不同文章中发现的内容,我认为oracle首先应用 rownum 子句,然后用于更新跳过锁定,因此所有线程都尝试更新前1024行。 我可以使用类似的东西:

select * from (select * from queue_requests where request_status = 0 and date_requested <= sysdate for update skip locked) where rownum <= ?

但这将锁定所有行,之后将返回其中的一部分。我不想锁定所有行。

我找到了一个创建存储过程的解决方案,但我不能改变数据库中的任何内容。我也发现了一些关于高级排队的东西,但我不确定我是否需要这么复杂的东西(我也找不到任何好的例子)。

这个问题有解决办法吗?

2 个答案:

答案 0 :(得分:3)

如果您希望每个线程只选择大约五分之一的记录,您可能会执行以下操作:

select *
from   queue_requests
where  request_status = 0 and
       date_requested <= sysdate and
       mod(DBMS_RowID.RowID_Row_Number(queue_requests.rowid),5) = thread_number
       rownum <= ?
for update
skip locked;

...其中thread_number是0到4之间的整数。

此成功取决于queue_requests表的每个块的可能行数。如果行很小,那么你就可以了,但是如果它们很大并且你有很多行,那么你可能会做得更好:

mod(DBMS_RowID.RowID_Block_Number(queue_requests.rowid),5)

答案 1 :(得分:0)

即使你不能交替你的数据库,你也可以执行一个PL / SQL块来使用游标进行“工作”实现:Execute anonymous pl/sql block and get resultset in java