【问题标题】:Oracle: how to limit number of rows in "select .. for update skip locked"Oracle:如何限制“select .. for update skip locked”中的行数
【发布时间】:2019-02-20 06:41:20
【问题描述】:

我有一张桌子:

table foo{
  bar number,
  status varchar2(50)
}

我有多个线程/主机,每个都在使用该表。每个线程更新状态,即悲观地锁定行。

在甲骨文 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. 我们正在考虑放弃 oracle。

【问题讨论】:

  • 与java无关

标签: sql oracle


【解决方案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;

【讨论】:

    猜你喜欢
    • 2021-12-05
    • 2016-01-29
    • 2019-04-16
    • 2011-04-25
    • 2018-08-18
    • 2019-10-19
    • 2016-08-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多