현상
DDL 수행 도중 lock 획득에 실패하여 12033 에러_LOCKFAIL_IN_NOWAIT가 발생합니다.
참고
12033 에러는 정상적으로 발생한 에러일 수 있습니다.
원인
다른 세션 또는 internal task 수행 간에 Lock을 요청하는 세션이 원인일 가능성이 높습니다.
해결
주의
Lock Fail 에러는 타이밍적으로 발생하는 에러이므로 재현이 어렵습니다.
따라서 이슈가 발생한 시점에 특정 자료를 확보하여 진행하는 것이 중요합니다.
CallStack Dump (Error)
DDL에서 lock을 설정하는 시점은 다양하므로, 어떤 시점에 lock fail이 발생하는지 확인이 가능한 경우 분석이 용이합니다.
•
'alter system dump callstack on error -12033 [on/off];' 명령어를 통해 Lock Fail 시 Callstack을 남길 수 있습니다. callstack dump는 성능 문제를 야기할 수 있으므로 반드시 필요할 때만 켜서 사용합니다.
CallStack Dump (Session)
lock fail 에러 발생이아닌, DDL 수행 상태로 hang과 유사한 현상이 발생한다면 이 방법을 사용합니다.
•
'alter system dump callstack [SID];' 명령어로 세션의 callstack을 수집할 수 있습니다.
•
SID는 DDL을 수행한 세션의 id이며, callstack dump는 5~10초 간격으로 5회 이상 반복 수행한 결과가 필요합니다.
GV$LOCK
GV$LOCK 뷰에서 모든 instance들이 점유한 WLOCK의 정보를 확인할 수 있습니다.
Single 구조는 V$LOCK만 조회해도 되며, TAC 상황에서는 반드시 GV$LOCK을 조회해야 합니다.
GV$LOCK의 컬럼 정보
컬럼정보 | 의미 |
INST_ID | Instance(node)의 ID
- Single일 경우 NULL 값 |
TYPE | WLOCK의 Type
- 특정 objeect에 ddl 시 WLOCK_DD_OBJ
- 권한 관련 ddl 시 (Grant , Revoke) WLOCK_DD_USER, WLOCK_DD_OBJAUTH, WLOCK_DD_SYSAUTH |
ID1,ID2 | lock 설정 시 사용되는 key
- 같은 type + 같은 key의 lock에 대해서만 경쟁
- WLOCK_DD_OBJ 의 경우 Object에 설정하는 Lock으로, ID1 은 해당 object 의 owner_id,
ID2 는 object id or name hash value |
SESS_ID | 해당 lock을 점유하거나 wait 중인 세션 id |
CTIME | 해당 lock을 잡거나 wait 중인 기간 (초) |
REQUESTED | wait 중인 lock mode |
LMODE | 점유 중인 lock mode |
1 : RS
2 : RX
3 : S
4 : SRX
5 : X
예시)
INST_ID TYPE ID1 ID2 LMODE REQUESTED SESS_ID CTIME
-------- ------------------------ ---------- ---------- ---------- ---------------- ----------- ----------
WLOCK_DD_OBJ 0 3265 0 1 98 137
WLOCK_DD_OBJ 0 3265 5 0 99 146
--WLOCK_DD_OBJ (0,3265)에 대해 session 99가 X LOCK을 146초 동안 잡고 있고
session 98이 RS LOCK을 획득하기 위해 137초 동안 wait 중이다
SQL
복사
Blocking Session 확인
DDL에서 LOCKFAIL_IN_NOWAIT 에러는 대부분 아래 사항에 해당합니다.
•
Object에 대한 DDL시 WLOCK_DD_OBJ를 획득하지 못함
•
권한과 관련된 DDL시 WLOCK_DD_USER, WLOCK_DD_OBJAUTH, WLOCK_DD_SYSAUTH 중 하나를 획득하지 못함
Blcoking Session 확인 방법
1.
sys.log에서 lock fail이 발생한 DDL 구문을 확인합니다.
2.
DDL 구문을 통해 ID1, ID2 값을 찾습니다.
3.
GV$LOCK에서 ID1, ID2 값으로 instance id, session id를 찾습니다.
4.
해당 instance id에 적용되는 sys.log에서 찾은 session로 검색합니다.
5.
해당 instance/session id를 통해 GV$SESSION에서 SQL_ID 를 확인하고, GV$SQL에 적용되는 SQL_TEXT를 확인합니다.
--1. SYS.LOG 에서 LOCKFAIL이 발생한 DDL 구문 확인
[DDL-99] [I] DDL execution failed (ec=-12033) drop table tibero.t;
--2. 구문을 통해 Lock의 ID 확인
SQL> select object_id from dba_objects where owner='TIBERO' and object_name='T';
OBJECT_ID
---------
3304
- WLOCK_DD_OBJ의 Lock을 ID2=3304로 설정하려다 실패했을 가능성
--3. GV$LOCK에서 해당 LOCK의 ID1, ID2 값으로 search 하여 instance id, session id 확인
SQL> select inst_id, sess_id from gv$lock where type='WLOCK_DD_OBJ' and id2=3304;
INST_ID SESS_ID
--------- --------
98
- Single 환경이므로 INST_ID는 Null, SESS_ID는 98
--4. SYS.LOG 확인
[DDL-98][I] Executing DDL : drop table tibero.t
[DDL-99][I] Executing DDL : drop table tibero.t
[DDL-99][I] THROW. ec=ERROR_LOCKFAIL_IN_NOWAIT(-12033) [ Lock acquisition failed in NOWAIT mode. ]
[DDL-99] [I] DDL execution failed (ec=-12033) drop table tibero.t;
- TIBERO.T table을 drop 시작했고 완료 로그가 없으므로 drop 중인 것을 알 수 있음
SQL
복사