选择以行限制锁定更新跳过
Posted
技术标签:
【中文标题】选择以行限制锁定更新跳过【英文标题】:Select for update skip locked with row limit 【发布时间】:2013-04-30 12:14:40 【问题描述】:我有一个用 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 子句,然后应用 for update skip locked,因此所有线程都会尝试更新前 1024 行。 我可能会使用类似的东西:
select * from (select * from queue_requests where request_status = 0 and date_requested <= sysdate for update skip locked) where rownum <= ?
但这会锁定所有行,然后返回其中的一部分。我不想锁定所有行。
我找到了一个创建存储过程的解决方案,但我无法更改数据库中的任何内容。我还发现了一些关于高级队列的东西,但我不确定我需要这么复杂的东西(我也没有找到任何好的例子)。
这个问题有解决办法吗?
【问题讨论】:
SKIP LOCKED 用于队列处理,即获取队列中下一个解锁的东西。所以这个想法是从堆栈顶部只取一件事。每次抓一小把表明你没有正确设计你的队列。我知道 FOR UPDATE SKIP LOCKED 允许我们选择多行,我只是认为我们不应该。 【参考方案1】:如果您希望每个线程只选择大约五分之一的记录,您可以执行以下操作:
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)
【讨论】:
您能解释一下为什么每个块的数量或行数很重要吗?【参考方案2】:即使您无法更改您的数据库,您也可以执行一个 PL/SQL 块以使用游标实现“工作”:Execute anonymous pl/sql block and get resultset in java
【讨论】:
以上是关于选择以行限制锁定更新跳过的主要内容,如果未能解决你的问题,请参考以下文章
根据条件限制/锁定所有 Post/Delete Rest API 端点 [关闭]