如何在Oracle中的同一个表中更新某些内容时检查行锁争用

时间:2017-06-30 07:09:01

标签: oracle transactions locking

如果同一行被另一个尚未提交的事务锁定,我怎样才能确保我的更新查询不等待提交?

我尝试在更新列之前使用触发器并且想要检查该行的争用但是因为如果在同一行上存在争用,则触发器本身不会被执行,我不得不删除该选项。这就是我设计触发器的方式,并希望检查内部开始的行争用

 <li class="start active" >
                <a href="{{  url('/admin/dashboard') }}">
                <i class="icon-home"></i>
                <span class="title">Dashboard</span>
                </a>
            </li>

但触发器也在排队。还有其他方法吗?如果我可以在发布后丢弃那些更新查询并检查等待相同行的争用,我也会很高兴。

1 个答案:

答案 0 :(得分:4)

您可以实施悲观锁定策略。这会尝试在发出提交之前获取锁:

 declare
     cursor c1 is
         select * from your_table
         where id = 1
         for update of whatever -- this is the pessimistic lock
         nowait -- abandon the attempt if row is already locked
         ;
     r1 c1%rowtype;
begin
    open c1;
    fetch c1 into r1;
    update your_table 
    set whatever = whatever + 1
    where current of c1;
    close c1;
    commit; -- release the lock
end;

此玩具代码具有NOWAIT,因此如果该行已被锁定,则查询将失败。我们也可以等待指定的超时或无限期等待(你现在正在做什么)。

SELECT ... FOR UPDATE语法的另一个优点是SKIP LOCKED,它允许我们实现排队。 Find out more

  

&#34;为什么触发不起作用?我的意思是当我在更新之前将其设置为运行时,它也不应该在行锁定之前执行。&#34;

那不是before update的含义。所有触发器都有效ON <<event>>。事件发生时触发器触发。触发器无法触发,直到该行实际更新为止。

beforeafter触发器指的是行的状态。在before update触发器中,我们可以引用:OLD值和操作:NEW值。在after update触发器中,我们可以引用:OLD值和:NEW值但不能更改:NEW值。