我有一个用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 <= ?
但这将锁定所有行,之后将返回其中的一部分。我不想锁定所有行。
我找到了一个创建存储过程的解决方案,但我不能改变数据库中的任何内容。我也发现了一些关于高级排队的东西,但我不确定我是否需要这么复杂的东西(我也找不到任何好的例子)。
这个问题有解决办法吗?
答案 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