有没有办法可以测试一行是否已被锁定以便在Oracle中进行更新?
- select * from SOME_TABLE where THE_ID = 1000 for update;
对于另一个用户,我想检查是否锁定了THE_ID = 1000的行.如果我尝试更新或某些东西,第二个用户被阻止并继续等待(不想这样).
- select * from SOME_TABLE where THE_ID = 1000 for update NOWAIT;
由于我不能在同一行上放置两个锁,因此会失败.确实如此.我得到一个“ORA-00054:资源忙,并通过NOWAIT指定的错误获取”.我是否可以始终依靠此错误来检查锁的存在,或者是否有更简单,更清晰的方法来确定行是否被锁定?
谢谢!
解决方法
您可以使用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
现在让我们用两个会话构建一个小例子:
- 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