Enqueue
1) 리소스 테이블
- 일종의 배열(Array)이다.
- Enqueue 리소스 구조체를 통합 관리하나 통합 관리하지 않고 버퍼 Lock이나 라이브러리 캐시 오브젝트처럼 개별 공유 리소스에서 소유자, 대기자 목록을 관리하는 경우도 있다.
- 해싱 알고리즘을 사용하여 각 리소스를 찾는다.
- 해시 키(Hash Key)는 리소스 식별자이며 각 해시 버킷에 연결 리스트(Linked List)로 연결된 해시 체인을 가지며, 여기에 리소스 구조체가 연결된다.
2) Enqueue 관리 방식에서의 Lock 획득 과정
Enqueue 방식으로 관리되는 특정 리소스(테이블, 트랜젝션 등)에 대한 Lock 획득 과정
[순서]
- 먼저 리소스 테이블에서 해당 리소스 구조체를 찾는다.
- 찾지 못하면 새로운 리소스 구조체를 할당받아 해시 체인 연결 리스트에 연결한다.
- 리소스 소유자 목록에 자신을 등록한다.
- 호환되지 않는 모드로 먼저 Lock을 획득한 세션이 있는 경우는 Lock 요청을 대기자 목록에 등록하고 대기(또는 작업을 포기)한다.
- 소유자가 Exclusive 모드일 때는 한 순간에 하나의 세션만 Lock을 소유할 수 있다.
- Shared 모드일 때는 여러 세션이 동시에 Lock 획득이 가능하다. 즉 , 동시에 소유자 목록에 등록할 수 있다.
- 소유자 목록에 어떤 모드건 Lock이 등록된 상태에서 Exclusive Lock을 획득하려면 대기자 목록에서 대기하고, 앞의 Lock이 모두 해제되면 소유자로 등록된다.
3) Enqueue Lock 작동 메커니즘
[순서]
- A 세션이 Shared 모드로 Lock을 획득한다.
- B 세션이 Shared 모드로 Lock을 획득한다.이 때 먼저 Lock을 소유한 A 세션과 호환되므로 정상적으로 Lock을 획득할 수 있다.
- 현재 소유자 목록에는 두 개의 세션이 존재한다.
- C 세션이 Exclusive 모드로 Lock을 획득하려할 때 Shared 모드와 Exclusive 모드 간에 호환성이 없으므로 대기자 목록에 자신(C 세션)을 등록하고 대기한다.
- 소유자 목록에 Shared 모드로 달려 있던 A, B 두 세션이 모두 Lock을 해제하면 C 세션이 Exclusive 모드로 소유자 목록에 등록한다.
- A 세션이 Exclusive 모드로 다시 Lock을 획득하려고 하면, Exclusive 모드와 호환되지 않으므로 대기자 목록에 자신(A)을 등록하고 대기한다.
- B 세션이 다시 Shared 모드로 Lock을 획득하려고 할 때도 Exclusive 모드와 호환되지 않으므로 대기자 목록에 자신(B)을 등록하고 대기한다.
- ⭐️ Enqueue Lock은 순서가 보장되므로 C 세션이 Lock을 해제하면 A 세션이 가장 먼저 Exclusive 모드로 Lock을 획득한다ㅏ.
Lock을 푸는 열쇠, 커밋
1) Lock 경합
블로킹
- Lock 경합이 발생해 특정 세션의 작업을 진행하지 못하고 멈춰 선 경우이다.
- 커밋 또는 롤백으로 해소한다.
교착상태(Deadlock)
- 두 세션이 각각 Lock을 설정한 리소스를 서로 액세스하려고 마주보고 진행하는 상황이다.
- 둘 중 하나가 물러나지 않으면 영영 풀릴 수 없다.
- 교착상태가 발생하면 이를 먼저 인지한 세션이 문장 수준 롤백을 진행한 후 에러 메시지를 던진다.
- ORA-00006: deadlock detected while waiting for resource
- 이 메시지를 받은 세션은 커밋 또는 롤백을 결정해야 한다.
- Lock 경합 때문에 대기 상태에 빠질 때 3초의 타임아웃을 설정하는 이유는 "교착상태 발생 인지" 하기 위해서이다.
- 해소후 교착상태는 해소됐지만 블로킹 상태에 놓이게 되며 이 에러에 대한 예외 처리(커밋 또는 롤백)을 하지 않으면 대기상태를 지속하게 되므로 주의해야 한다.
2) 오라클은 데이터를 읽을 때 Lock을 사용하지 않음
- 오라클은 데이터를 읽을 때 Undo를 활용하고 Lock을 사용하지 않아 다른 DBMS에 비해 상대적으로 Lock 경합이 적게 발생한다.
- 읽는 세션의 진행을 막는 부담이 없어 필요한 만큼 트랜잭션을 충분히 길게 가져갈 수 있다.
- 하지만 트랜잭션이 너무 길면 롤백이 필요한 경우 너무 많은 시간이 걸리며 Undo 세그먼트가 고갈되거나 Undo 세그먼트 경합을 유발한다.
- DML Lock 때문에 동시성이 저하되지 않도록 적절한 시점에 커밋해야하지만 너무 자주 하면 Snapshot too old(ORA-01555) 에러를 유발할 가능성 높아진다.
- LGWR가 로그 버퍼를 비우는 동안 발생하는 log file sync 대기 이벤트 때문에 성능 저하의 우려도 생긴다.
- 잦은 커밋 때문에 성능이 느리다면 비동기식 커밋 기능 활용을 검토해야 한다.(10gR2부터 제공)
커밋 명령 옵션
1. WAIT(Default)
- LGWR가 로그버퍼를 파일에 기록했다는 완료 메시지를 받을 때까지 대기한다.
- 그동안 log file sync 대기 이벤트가 발생하며 이를 '동기식 커밋'이라고도 한다.
- 일반적인 커밋(immediate wait)에서는 트랜잭션 데이터가 데이터베이스에 안전하게 저장됨을 보장한다.
2. NOWAIT
- LGWR의 완료 메시지를 기다리지 않고 바로 다음 트랜잭션을 진행한다.
- log file sync 대기 이벤트가 발생하지 않는다. 이를 '비동기식 커밋'이라고도 한다.
- 트랜잭션 커밋 직후 인스턴스에 문제가 생기거나, Redo 로그가 위치한 파일 시스템에 문제가 생겨 쓰기 작업을 진행할 수 없게 되면 커밋이 정상적으로 완료되지 못할 우려가 있다.
- 커밋 명령을 받을 때마다 LGWR가 로그 버퍼를 파일에 기록한다.
4. BATCH
- 세션 내부에 트랜젝션 데이터를 일정량 버퍼링했다가 일괄 처리한다.
- PGA 메모리 할당량이 늘어난다.
COMMIT WRITE IMMEDIATE WAIT ;
COMMIT WRITE IMMEDIATE NOWAIT ;
COMMIT WRITE BATCH WAIT ;
COMMIT WRITE BATCH NOWAIT ;