【问题标题】:JPA: Pessimistic locking of a row with select for update in OracleJPA:在 Oracle 中使用 select for update 对行进行悲观锁定
【发布时间】:2021-03-16 13:12:24
【问题描述】:

我得到一个包含如下数据的 oracle 表:

表:

create table myobjects(id int, objname varchar(20), state int);

数据:

id / objname / state
1 / 'object no. 1' / 2
2 / 'object no. 2' / 1
3 / 'object no. 3' / 1
4 / 'object no. 4' / 1
5 / 'object no. 5' / 1
6 / 'object no. 6' / 1
7 / 'object no. 7' / 1

现在我应该有多个批处理实例

  1. 锁定表的一个对象行,状态 = 1(语句应返回最多一个对象行,第一个可用/未锁定的对象行,如果没有可用,则可以找到或没有行)
  2. 将对象行的状态设置为2,提交,
  3. 为该行做一些工作,将状态设置为 3 并提交。

为了生成语句,我使用 openjpa...但如果需要,也可以使用 oracle 原生语句。

对于第 1 步,我尝试了以下语句:

select * from myobjects where state = 1 and rownum <= 1 for update skip locked;

==> 锁定所有状态为 1 的对象,rownum

所以第一批实例会锁定所有对象 --> 不好

我可以想到的另一种可能性(回退)是选择(例如)状态为 1 的 10 行,没有锁定和 然后通过 id 锁定一行:

select * from myobjects where state = 1 and rownum <= 10;
-- 'try and error' locking with all of them
select * from myobjects where id = :id for update;

==> 确实需要很多 sql 调用... --> 必须有更好的解决方案

您能帮我找到更好的解决方案吗?

提前致谢。

P.S.:请:解决方案,没有存储过程,只有。

【问题讨论】:

  • 怎么样:select * from myobjects where state = 1 and id in (select min(id) from myobjects where state = 1) 进行更新
  • 你正在尝试重新实现一个排队系统,所以你可能想检查Oracle AQ的实现,但问题是你为什么不使用它或一些JMS 实现?那里有很多 DIY 排队解决方案,但它们通常不会扩展并且倾向于不时“挂起”......
  • @aschoerk:使用此解决方案,两个批处理实例尝试锁定同一对象行。第二次调用总是不返回结果。不是我需要的。我需要的是,每个批处理实例都会锁定下一个可用的对象行。上面没有提到这个要求 - 我已经添加了。
  • @Marmite Bomber:“重新实现排队系统”。是的,我正在这样做。你能帮我吗?
  • 是否可以使用线程/批次特定的状态 uuid。然后执行“update myobjects set state = uuid where state = 1 and id in (select min(id) from myobjects where state = 1)” select id from myobjects where state = uuid 你不需要为此使用悲观锁定。锁定是通过使用您在状态中的特定标识符来完成的

标签: sql oracle jpa locking openjpa


【解决方案1】:

是否允许使用 PL/SQL?试试:

declare
   id int;
begin
   update myobjects
   set state=2
   where state = 1
   and rownum = 1 
   returning id into id;

   commit;

   dbms_output.put_line(id);
end;

它适用于我使用 2 个独立的 SQL Developer 会话。

【讨论】:

  • 抱歉,不能使用 PL/SQL。
  • @markus,为什么不呢?使用 Oracle 数据库而不使用它附带的强大功能是没有意义的。
  • 我们尝试尽可能地独立于数据库......也许有一天另一个数据库会使用不同的低级语言放在路线图上。那么,所有这些低级代码都必须重新编写。我什至想知道'for update skip locked'是否是个好主意......
  • 'for update' 是 jpa 添加的,但跳过锁定不是。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-10
  • 2016-12-01
  • 2015-07-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多