如何在 Oracle SQL 中锁定单行

How can I lock a single row in Oracle SQL

这看起来很简单,但我很难做到。问题是我如何锁定 table JOBS 中的一行 JOB_ID = IT_PROG.我想这样做,因为我想尝试一个过程的异常,当您尝试更新锁定的行时,它会向您显示一条消息。提前感谢您的宝贵时间。

A​​skTom 有一个您尝试执行的示例:

https://asktom.oracle.com/pls/apex/f?p=100:11:0::::P11_QUESTION_ID:4515126525609

来自 AskTom:

    declare
            resource_busy   exception;
            pragma exception_init( resource_busy, -54 );
            success boolean := False;
    begin

        for i in 1 .. 3
        loop
             exit when (success);
             begin
                         select xxx from yyy where .... for update NOWAIT;
                         success := true;
             exception
                         when resource_busy then
                                 dbms_lock.sleep(1);
             end;
         end loop;

         if ( not success ) then
                     raise_application_error( -20001, 'row is locked by another session' );
         end if;
    end;

这会尝试获取锁,如果无法获取锁(即 ORA-00054:资源繁忙并使用指定的 NOWAIT 获取或引发超时),它将引发错误。

您可以按照其他答案中的描述锁定记录,但是在更新此行时您将看不到任何异常

UPDATE 语句将等待直到锁被释放,即 SELECT ... FOR UPDATE 的会话提交。之后将执行更新。

您唯一可以管理的例外是死锁,即

Session1   SELECT FOR UPDATE record A
Session2   SELECT FOR UPDATE record B
Session1   UPDATE record B  --- wait as record locked
Session2   UPDATE record A  --- deadlock as 1 is waiting on 2 and 2 waiting on 1

无法在 Oracle 中手动锁定行。不过,您可以手动锁定对象。排他锁在执行 DML 操作时自动放置在行上,以确保没有其他会话可以更新同一行或任何其他 DDL 操作可以删除该行 - 其他会话可以随时读取它。

第一个请求锁定行的会话获得它,任何其他请求写访问的会话必须等待。
如果你不想被锁定,也就是说,如果你不想等待,你可以使用

Select .... For update ( nowait / wait(n) ) ( skiplocked) 声明