oracle skip locked 报错 00054

skip locked 锁不住应该会跳过,怎么还会报这个错呢?不得其解

Skip Locked 主要是为了在多用户环境中使用而设计的。它我们在执行DML语句的时候跳过锁定的行,直接获取未锁定的行。所以理论上你使用了skip locked 应该是获取未锁定的行而不应该是报错。
但有另外一种情况,比如有用户对表进行进行LOCK操作例如
LOCK TABLE XXXX IN EXCLUSIVE MODE。
这时候你再对表进行DML类的操作,例如
select * from XXXX for update skip locked
这时候该语句仍然是被阻塞的。你的错误是否可能是因此而超时导致的报错?

Oracle Skip Locked

Oracle 11g引入skip locked。
Skip Locked 是在query select语句中跳过已经被其他正在执行的query select语句锁住的行,只执行能够获得锁的行。

select for update如何查询大数量,那么其他session同时执行的select语句可能会等待锁超时而报下面这个错

ORA-30006: resource busy; acquire with WAIT timeout expired

如果是不超时的case,那么会出现

ORA-00054 resource busy and NOWAIT specified

比如session1执行下面语句:

SELECT *
  FROM dept  WHERE
 deptno = 10
FOR UPDATE NOWAIT;

输出:

DEPTNO     DNAME          LOC
---------- -------------- -------------
10         ACCOUNTING     NEW YORK

session2执行下面语句:

SELECT * FROM dept
 WHERE deptno IN (10,20)
FOR UPDATE NOWAIT;

那么输出:

SELECT * FROM dept WHERE deptno IN (10,20)
FOR UPDATE NOWAIT
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified

因为session1已经锁住10这一行,session2请求获得不到10这一行的锁,就报错了。

那么在session2我们可以使用skip locked

SELECT * FROM dept
 WHERE deptno IN (10,20)
FOR UPDATE SKIP LOCKED;

此时输出:

DEPTNO     DNAME          LOC
---------- -------------- -------------
20         RESEARCH       DALLAS

SKIP LOCKED会跳过被锁住的行,只查询没有锁住的行。