我有一张桌子:
table foo{
bar number,
status varchar2(50)
}
我有多个线程/主机,每个线程/主机都在使用该表。每个线程都会更新状态,即悲观地锁定行。
在oracle 12.2中
select ... for update skip locked
似乎可以完成工作,但是我想限制行数。新的FETCH NEXT
听起来不错,但是我语法不正确:
SELECT * FROM foo ORDER BY bar
OFFSET 20 ROWS FETCH NEXT 10 ROWS ONLY
FOR UPDATE SKIP LOCKED;
最简单的方法是什么,即使用最少的代码 1 (理想情况下不带pl / sql函数)?
我想要这样的东西:
select * from (select * from foo
where status<>'baz' order by bar
) where rownum<10 for update skip locked
PS 1.我们正在考虑摆脱甲骨文。
答案 0 :(得分:1)
我建议创建pl / sql函数并使用动态sql来控制锁定记录的数量。该锁在获取时获取。因此,获取N条记录会自动将其锁定。请记住,一旦完成事务(提交或回滚),记录便会解锁。 以下是锁定N条记录并以数组形式返回其ID值的示例(假设您已在表中添加了主键ID列):
create or replace function get_next_unlocked_records(iLockSize number)
return sys.odcinumberlist
is
cRefCursor sys_refcursor;
aIds sys.odcinumberlist := sys.odcinumberlist();
begin
-- open cursor. No locks so far
open cRefCursor for
'select id from foo '||
'for update skip locked';
-- we fetch and lock at the same time
fetch cRefCursor bulk collect into aIds limit iLockSize;
-- close cursor
close cRefCursor;
-- return locked ID values,
-- lock is kept until the transaction is finished
return aIds;
end;
sys.odcinumberlist
是内置数字数组。
这是要在db中运行的测试脚本:
declare
aRes sys.odcinumberlist;
begin
aRes := get_next_unlocked_records(10);
for c in (
select column_value id
from table(aRes)
) loop
dbms_output.put_line(c.id);
end loop;
end;