본문 바로가기

DB/Oracle

테이블 LOCK

반응형

작업을 하는데 특정 테이블의 update가 안되는 이슈가 있었다.

단순 오류가 아니라 update 쿼리 실행시 db가 그대로 잠겨 페이지 또한 올라오지 않았다.

원인을 먼저 찾아보기위해 세션을 확인하기 위한 쿼리를 실행했다.

SELECT
    A.USERNAME AS 계정명,
    A.SCHEMANAME AS 스키마명,
    A.STATUS AS 활성화여부,
    A.SID AS 세션식별자,
    A.SERIAL# AS 시리얼번호,
    A.MACHINE AS OS머신명,
    A.PROGRAM AS OS프로그램명,
    A.TYPE AS 세션타입,
    A.LOGON_TIME AS 세션로그인날짜,
    B.FIRST_LOAD_TIME AS 처음실행한시각,
    B.SQL_TEXT  AS 실행쿼리,
    C.TYPE AS 락타입
FROM
    V$SESSION A, V$SQLAREA B, v$lock C
WHERE
    (A.SQL_HASH_VALUE = B.HASH_VALUE  --SQL_HASH_VALUE : 가장 최근 실행된 SQL의 HASH값
    OR A.PREV_HASH_VALUE = B.HASH_VALUE) --PREV_HASH_VALUE : 이전에 실행된 SQL의 HASH값
    AND
    A.SQL_ADDRESS = B.ADDRESS
    AND A.sid = C.sid
    --AND A.USERNAME = '계정명' -- 특정 계정의 세션만 조회
    --AND A.STATUS = 'ACTIVE' --활성화된 세션만 조회
;

 

찾아봤더니 여러개의 inactive, active 쿼리들이 보였는데 그 중 락타입 필드에 TX, TM 이라는 것이 눈에 보였다.

락의 종류는 다음과 같다

 

TM의 경우 테이블 자체가 LOCK이 걸렸다는 것 이고

TX의 경우 해당 Row 만 LOCK이 걸렸다는 것 이였다.

 

일단 update를 했던 세션을 kill 하고 새로 돌려보았다.

ALTER SYSTEM KILL SESSION '세션식별자,시리얼번호';

 

이후 다시 update를 했더니 그대로 진행이 되지 않았다.

 

원인을 찾아보기 위해 같은 테이블 다른 row를 업데이트 했더니 이상없이 잘 되었다.

 

그 row를 잡고 있는 무언가가 있다는건데 찾기가 힘들어서 일단 모든 세션을 kill 하고 새로 돌려봤더니...

이상없이 update가 잘 되었다.

일단 해결은 했다만... 예상가는게 하나 있긴하다.

오라클을 사용하며 키값을 위해 sequence 를 사용하고 있었는데 그 부분이 문제인듯하다.

insert 를 하며 F_FIELD_SEQ.nextval 을 사용하는데 문제는 이 insert가 정상작동 하지 않았을 때 생긴듯하다.

 

문제가 생긴 row 는 가장 최근에 생긴 데이터였다. 예를 들어 이 시퀀스 번호가 100 번이라고 하자.

이후 insert를 위해서는 100번을 조회하며 시퀀스가 nextval 이 실행이 되어야하는데 해당 insert문이 제대로 실행되지않자

nextval 이 100번 시퀀스를 보고 있는 상태로 멈추며 해당 100번 시퀀스의 row가 lock 이 걸린게 아닌가 싶다.

그래서 100번을 제외한 이전 시퀀스들은 정상적인 update가 이뤄졌던게 아닐까... 라고 생각한다.

 

그냥 예상으로만 두기에는 찝찝하긴한데 저 insert문에서 어떻게 오류가 나서 rollback이나 commit 이 되지 않았던 건지를 못 찾았다. 

오류는 내기위해 이것저것 실행해보는데도 정상적인 rollback이 되는지라... 일단 lock에 대해 어림짐작으로나마 하나 알게된 것 으로 일단 만족하고 나중에 다시 비슷한 이슈가 발생하면 염두해두는 것 으로 마무리하자.