【发布时间】: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(语句应返回最多一个对象行,第一个可用/未锁定的对象行,如果没有可用,则可以找到或没有行)
- 将对象行的状态设置为2,提交,
- 为该行做一些工作,将状态设置为 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