[Oracle] ORA-00054 리소스가 사용 중이어서 NOWAIT가 지정되었거나 시간 초과가 만료된 상태로 획득합니다.

다음 오라클 에러에 대해서 알아보도록 하자.

ORA-00054: 리소스가 사용 중이어서 NOWAIT가 지정되었거나 시간 초과가 만료된 상태로 획득합니다.
resource busy and acquire with NOWAIT specified.

 

1. commit을 안해서 LOCK걸린 경우
나의 경우에는 테이블 특정 컬럼의 길이를 변경하는 스크립트를 실행을 시키다가 에러가 발생하였다. 
발생되는 원인을 확인해보니 다음과 같았다. 
나를 포함한 누군가가 해당 테이블에 스크립트를 실행하고 커밋을 하지 않은 경우.
때문에, 해당 테이블에 진행 중인 트랜잭션이 완료되기 전까지는 LOCK에 걸려 작업을 할 수 없게 된다. 작업 중인 사용자를 찾아서 해당 테이블에 진행 중인 트랜잭션을 commit처리를 해야 한다.

 

DB developer 툴에서의 트랜잭션 모드는 auto-commit과 manual-commit (not auto-commit)이 있다.
대부분 auto-commit을 사용하면, 위의 문제는 발생되지 않으나 rollback할 수 없이 바로 적용되는 단점이 있다. 

auto-commit이 아닌 경우에는, commit을 하기 전까지는 다른 작업자는 테이블을 사용할 수 없지만 문제 발생 시 대처할 수 있다. 

각자의 장단점이 있지만, 대부분 auto-commit이 더 위험한 문제가 발생될 수 있으니 지양한다고 알고 있다.

 

하지만, 위와 같은 경우가 아니라도 발생될 수 있다.
2. 비정상적인 종료로 인해 LOCK걸린 경우
1명의 사용자가 사용 중인 DB에서 LOCK이 걸린다면 1번의 경우 말고도 비정상적으로 실행 중인 DML을 종료할 때 LOCK이 발생될 수 있다. 이런 경우에는 해당 실행 중인 트랜잭션의 세션을 직접 kill하면 된다.


사용 중인 DB계정이 세션 관련 테이블에 접근할 수 있다는 가정하에 아래의 내용을 실행한다.

--먼저 SESSION_ID와 SERIAL_NO추출
SELECT A.SESSION_ID AS SESSION_ID
    , B.SERIAL# AS SERIAL_NO
    , A.OS_USER_NAME
    , A.ORACLE_USERNAME
    , B.STATUS
FROM v$locked_object A, v$session B
WHERE 1=1
AND A.SESSION_ID = B.SID

--추출된 SESSION_ID의 세션 KILL
ALTER SYSTEM KILL SESSION 'SESSION_ID, SERIAL_NO';