1

我有一个用 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):

线程 0 更新 1024

线程 4 更新 0

线程 1 更新 0

线程 2 更新 0

线程 3 更新 0

因此,只有一个线程找到要更新的行。从我在不同文章中发现的内容来看,我认为 oracle 首先应用rownum子句,然后再应用update skip locked,因此所有线程都尝试更新前 1024 行。我可能会使用类似的东西:

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

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

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

这个问题有什么解决办法吗?

4

2 回答 2

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)
于 2013-04-30T12:43:23.003 回答
0

即使您无法更改您的数据库,您也可以执行一个 PL/SQL 块以使用游标实现“工作”:执行匿名 pl/sql 块并在 java 中获取结果集

于 2017-06-21T12:12:01.867 回答