CUBRID에서 lock정보는 lockdb 유틸리티를 통하여 확인이 가능합니다.
이곳에서는 CUBRID 9.3.3 버전을 기준으로 lockdb의 사용법 및 확인 방법을 제공합니다.
관련 메뉴얼 : cubrid 유틸리티 - 잠금(lock) 상태 확인
1. lockdb 사용 방법
$ cubrid lockdb [option] database_name
옵션이 없이 lockdb를 사용할 경우 lock 정보를 화면에 출력하며, -o 옵션을 사용하여 출력 파일을 지정하면 lock 정보를 파일 형태로 저장할 수 있습니다.
ex) cubrid lockdb -o ./output.txt database_name
2. 출력 내용 설명
출력 내용은 3개의 섹션으로 이루어져 있으며 다음과 같습니다.
- 서버에 대한 잠금 설정 정보 (Lock Table Dump)
- 현재 데이터베이스에 접속한 클라이언트들 정보
- 객체 잠금 테이블의 정보 (Object Lock Table)
2-1. 첫 번째 섹션 : 서버에 대한 잠금 설정 정보
- Lock Escalation : row에 대한 lock이 table lock으로 확대되기 전에 개별 행에 허용되는 최대 lock 개수를 의미
위의 정보에서는 10만개의 row에 lock이 발생할 경우, table lock으로 변경됩니다.
관련 파라미터 : lock_escalation
- Run Deadlock interval : 중단된 트랜잭션에 대한 교착 상태(deadlock) 여부를 탐지하는 주기를 나타내며
단위는 초(second) 입니다.
관련 파라미터 : deadlock_detection_interval_in_secs
2-2. 두 번째 섹션 : 현재 데이터베이스에 접속한 클라이언트들 정보
두 번째 섹션의 정보는 각각의 클라이언트에 대한 트랜잭션 인덱스, 프로그램 이름, 사용자 ID, 호스트 이름, 프로세스 ID, 격리 수준, 잠금 타임아웃 설정이 포함됩니다. 위의 내용을 확인해보면 다음과 같습니다.
- 트랜잭션 인덱스 : 1
- 프로그램 이름 : broker1_cub_cas_1
- 사용자 ID : DBA
- 호스트 이름 : newTest1
- 프로세스 ID : 10929
- 격리 수준 : REPEATABLE CLASSES AND READ UNCOMMITTED INSTANCES (isolation leve 3)
- 잠금 타임아웃 : 1초
2-3. 세 번째 섹션 : 객체 잠금 테이블의 정보
세 번째 섹션에는 어떤 객체에 대해서 어떤 클라이언트가 어떤 모드로 잠금을 가지고 있는지,
어떤 객체에 대해서 어떤 클라이언트가 어떤 모드로 기다리고 있는지를 보여줍니다.
객체 잠금 테이블 정보의 첫 부분에는 얼마나 많은 객체가 잠금되었는지가 출력됩니다.
2-3-1. lock이 없을 경우
2-3-2. lock이 존재할 경우
객체 잠금 테이블의 정보에서 두 번째 부분부터는 lock을 획득한 각각의 객체에 대한 객체의 OID와 Object type, 테이블 이름이 출력됩니다.
추가적으로 lock을 보유하고 있는 트랜잭션의 개수(Num holders),
lock을 보유하고 있지만 상위 lock으로 변환되지 못하고 차단된 트랜잭션의 개수(Num blocked-holders),
객체의 lock을 기다리는 다른 트랜잭션의 개수(Num waiters)가 출력됩니다.
또한 lock을 보유하고 있는 클라이언트 트랜잭션, 차단된 클라이언트 트랜잭션, 기다리는 클라이언트 트랜잭션의 리스트가 출력됩니다.
* 테이블에 lock이 발생하였을 경우에 Nsubgranules가 출력되는데
이는 테이블 내의 특정 트랜잭션이 획득하고 있는 row lock과 index lock의 개수를 합한 것 입니다.
2-3-4. lock 모드 : 메뉴얼 참조 (잠금 프로토콜)
2-3-5. lock 예제
- 시나리오
(1) lock_test 테이블을 생성
(2) lock_test 테이블에 데이터 INSERT
(3) CUBRID Manager에서 UPDATE 질의 수행 후 commit 혹은 rollback을 수행하지 않음
(4) csql에서 동일한 row에 UPDATE를 수행
(5) lockdb 유틸리티를 통해 lock 정보 확인
(6) lock.log (lock 출력 내용) 해석
- 첫 번째 섹션 : 서버에 대한 잠금 설정 정보
-> lock escalation은 기본값은 10만이며, 교착 상태(deadlock) 탐지 시간은 1초로 설정
- 두 번째 섹션 : 현재 데이터베이스에 접속한 클라이언트들 정보
-> index가 0일 경우 내부적인 시스템 트랜잭션입니다.
해당 트랜잭션은 데이터베이스의 체크포인트 수행과 같이
특정한 시간에 lock을 획득할 수 있지만 대부분의 경우 어떠한 lock도 획득하지 않을 것 입니다.
-> csql에서 DBA 계정으로 접속한 클라이언트 입니다. lock 타임아웃은 무한으로 설정되어 있습니다.
-> query_editor (CUBRID Manager)에서 DBA 계정으로 접속한 클라이언트 입니다.
lock 타임아웃은 무한으로 설정되어 있습니다.
-> query_editor (CUBRID Manager)에서 DBA 계정으로 접속한 클라이언트 입니다.
lock 타임아웃은 무한으로 설정되어 있습니다.
-> lockdb는 lock정보를 DB에 접속하여 가져오는 하나의 클라이언트이기 때문에
lockdb 수행시 클라이언트 정보로 출력됩니다.
- 세 번째 섹션 : 객체 잠금 테이블의 정보
-> 현재 6개의 lock이 발생하였습니다.
-> lock_test 라는 테이블에 IX_LOCK(의도 베타 잠금)이 설정되었습니다.
해당 lock은 특정 row에 X_LOCK이 발생할 경우 상위 객체인 테이블에서 발생하는 lock 입니다.
이때에는 스키마 변경이 불가능하며 테이블 전체의 row에 대한 갱신 및 조회가 불가능 합니다.
상위 lock으로 변환하려다 차단된 트랜잭션 (Num blocked-holders)는 0이며,
해당 객체에 대한 lock을 잡기 위해 기다리는 트랜잭션 (Num waiters)도 0 입니다.
LOCK HOLDERS 부분에는 현재 lock으로 인해 대기상테인 트랜잭션 정보가 표시되는데
Tran_index가 1, 2인 query_editor(CUBRID Manager)가 대기중인 상황을 알 수 있습니다.
두 트랜잭션 모두 획득하려는 lock의 종료는 IX_LOCK입니다.
-> pk_lock_test_col1 이라는 index에 NX_LOCK(다음 키 베타 잠금)이 설정되었습니다.
해당 lock은 고유 키가 존재하는 row에 대해 UPDATE, DELETE를 수행할 때
해당 작업이 영향을 주는 범위를 보호하기 위해 해당 키의 이전과 다음 키에 lock을 설정합니다.
따라서, 1개의 row가 UPDATE, DELETE 될 경우 2개의 NX_LOCK이 발생합니다.
즉, 첫 번째 NX_LOCK에 대한 정보 입니다.
-> pk_lock_test_col1 이라는 index에 NX_LOCK(다음 키 베타 잠금)이 설정되었습니다.
위의 NX_LOCK 외 두 번째 NX_LOCK 정보 입니다.
-> Root class란 특정 row에 X_LOCK이 발생하여 상위 객체인 테이블 (class)에 IX_LOCK이 발생할 경우
상위 객체를 지칭하는 Object type을 의미 합니다.
즉, lock_test에서 IX_LOCK이 발생한 정보 입니다.
-> 시스템 테이블 중 하나인 db_serial에 IS_LOCK(의도 공유 잠금)이 설정되었습니다.
IS_LOCK은 특정 row에 대한 읽기 연산이 수행됨에 따라 해당 row에 S_LOCK이 발생하면서
그 상위 객체인 테이블의 갱신을 막기 위해 발생하는 lock 입니다.
여기서는 lock_test 테이블에 col1 컬럼이 auto_increment 속성으로 되어 있어서
해당 serial 값을 조회하면서 발생한 lock 입니다.
-> 드디어 lock의 원인이 된 트랜잭션을 찾았습니다.
Object type이 Instance of class 이므로 lock_test 테이블의 row에 발생한 X_LOCK 입니다.
X_LOCK(베타 잠금)은 객체에 대한 갱신 연산을 수행하기 전에 획득하며,
단 하나의 트랜잭션만 획득할 수 있는 lock 입니다.
X_LOCK을 획득한 트랜잭션이 끝나기 전까지는 다른 트랜잭션들은 해당 객체에 대해
읽기 및 갱신 연산을 수행할 수 없습니다.
LOCK HOLDERS (lock 소유자)는 Tran_index 2인 query_editor(CUBRID Manager)이며
획득한 lock 종류는 X_LOCK 입니다.
LOCK WAITERS (lock 대기자)는 Tran_idex 1인 csql이며 lock 종류는 U_LOCK 입니다.
U_LOCK(갱신 잠금)은 갱신 연산을 수행하기 전,
조건절(WHERE 절)에서 읽기 연산을 수행할 때 획득하는 lock 입니다.
현재 CUBRID Manager에서 X_LOCK을 획득한 상태이므로
csql에서 UPDATE를 수행하기 위해 조건절 (WHERE 절)을 조회하는 과정에서
U_LOCK을 획득하지 못하고 대기 상태로 설정된 상황 입니다.
Start_waiting_at은 대기가 시작된 시간으로 2015-12-8 09:36:00 인 것을 확인할 수 있으며
Wait_for_secs는 대기 시간으로 -1이므로 무한이라는 것을 확인할 수 있습니다.
CUBRID에서 lock을 확인하기 위해 cubrird lockdb 유틸리티를 사용하는 방법을 간단하게(?) 알아보았습니다.
감사합니다.