如何检查行是否被锁定以进行更新?

8 sql oracle ora-00054

有没有办法可以测试一行是否已被锁定以便在Oracle中进行更新?

例如,假设由一个用户执行以下查询:

select * from SOME_TABLE where THE_ID = 1000 for update;
Run Code Online (Sandbox Code Playgroud)

对于另一个用户,我想检查行THE_ID = 1000是否被锁定.如果我尝试更新或第二个用户被阻止并继续等待(不想这样).

我还尝试与第二个用户运行以下查询:

select * from SOME_TABLE where THE_ID = 1000 for update NOWAIT;
Run Code Online (Sandbox Code Playgroud)

由于我不能在同一行上放置两个锁,因此会失败.确实如此.我得到一个"ORA-00054:资源忙,并通过NOWAIT指定的错误获取".我是否可以始终依靠此错误来检查是否存在锁定,或者是否有更简单,更清晰的方法来确定是否锁定了行?

谢谢!

Vin*_*rat 16

您可以使用FOR UPDATE NOWAIT编写一个过程,并在该行被锁定时返回错误消息:

SQL> CREATE OR REPLACE PROCEDURE do_something(p_id NUMBER) IS
  2     row_locked EXCEPTION;
  3     PRAGMA EXCEPTION_INIT(row_locked, -54);
  4  BEGIN
  5     FOR cc IN (SELECT *
  6                  FROM some_table
  7                 WHERE ID = p_id FOR UPDATE NOWAIT) LOOP
  8        -- proceed with what you want to do;
  9        NULL;
 10     END LOOP;
 11  EXCEPTION
 12     WHEN row_locked THEN
 13        raise_application_error(-20001, 'this row is locked...');
 14  END do_something;
 15  /

Procedure created
Run Code Online (Sandbox Code Playgroud)

现在让我们用两个会话构建一个小例子:

session_1> select id from some_table where id = 1 for update;

        ID
----------
         1

session_2> exec do_something(1);

begin do_something(1); end;

ORA-20001: this row is locked...
ORA-06512: at "VNZ.DO_SOMETHING", line 11
ORA-06512: at line 2

session_1> commit;

Commit complete

session_2> exec do_something(1);

PL/SQL procedure successfully completed
Run Code Online (Sandbox Code Playgroud)