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

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

【讨论】:

以上是关于选择以行限制锁定更新跳过的主要内容,如果未能解决你的问题,请参考以下文章

选择从 JPA 级别锁定的更新跳过

为啥在选择的更新跳过锁定时,若有的几个会话可以看到行?

根据条件限制/锁定所有 Post/Delete Rest API 端点 [关闭]

如何在 postgres 中使用“更新跳过锁定”而不锁定查询中使用的所有表中的行?

怎么锁定CPU频率

猫鼬跳过、限制和计数