6.4.1 오라클 Lock
- 애플리케이션 개발 측면에서 가장 중요하게 다루어야 할 Lock은 무엇보다 DML Lock이다
- 다중 트랜잭션이 동시에 액세스하는 사용자 데이터의 무결성을 보호해준다
DML 로우 Lock
두 개의 동시 트랜잭션이 같은 로우를 변경하는 것을 방지한다
- Insert에 대한 로우 Lock 경합은 Unique 인덱스가 있을 때만 발생한다
- Unique 인덱스가 있는 상황에서 두 트랜잭션이 같은 값을 입력하려고 할 때, 블로킹이 발생한다
- 두 트랜잭션이 서로 다른 값을 입력하거나 Unique 인덱스가 아예 없으면, Insert에 대한 로우 Lock 경합은 발생 X
- 오라클에서는 DML과 Select 는 서로 진행을 방해하지 않는다
- DML 끼리는 서로 방해할 수 있다
- 참고) MVCC 모델을 사용하지 않는 DBMS는 Select 문에 공유 Lock을 사용한다
DML 테이블 Lock
- 오라클은 DML 로우 Lock을 설정하기에 앞서 테이블 Lock을 먼저 설정한다
- 현재 트랜잭션이 갱신 중인 테이블 구조를 다른 트랜잭션이 변경하지 못하게 막기 위해서
- 테이블 Lock은 테이블 전체에 Lock이 걸리는 것이 아니다
- 자신(테이블 Lock을 설정한 트랜잭션)이 해당 테이블에서 현재 어떤 작업을 수행 중인지 알리는 일종의 푯말(flag)
대상 리소스가 사용 중일 때, 진로 선택
Lock을 얻고자 하는 리소스가 사용 중일 때, 프로세스는 아래 3가지 방법 중 하나를 사용한다
사용자가 이 세가지 옵션을 모두 선택할 수 있는 문장이 바로 SELECT FOR UPDATE 문이다
- Lock이 해제될 때 까지 기다린다 (select * from t for update)
- 일정 시간만 기다리다 포기한다 (select * from t update wait 3)
- 기다리지 않고 작업을 포기한다 (select * from t for update nowait)
Lock을 푸는 열쇠, 커밋
- WAIT(Default) : LGWR가 로그버퍼를 파일에 기록했다는 완료 메시지를 받을 대까지 기다린다 (동기식 커밋)
- NOWAIT : LGWR의 완료 메시지를 기다리지 않고 바로 다음 트랜잭션을 진행한다 (비동기식 커밋)
- IMMEDIATE(Default) : 커밋 명령을 받을 때마다 LGWR가 로그 버퍼를 파일에 기록한다
- BATCH : 세션 내부에 트랜잭션 데이터를 일정량 버퍼링 했다가 일괄 처리한다
이들 옵션을 조합해 아래 네 가지 커밋 명령을 사용할 수 있다
COMMIT WRITE IMMEDIATE WAIT; ------1
COMMIT WRITE IMMEDIATE NOWAIT; ----2
COMMIT WRITE BATCH WAIT; ----------3
COMMIT WRITE BATCH NOWAIL; --------4
6.4.2 트랜잭션 동시성 제어
비관적 동시성 제어 : 사용자들이 같은 데이터를 동시에 수정할 것으로 가정, Lock을 건다
낙관적 동시성 제어 : 사용자들이 같은 데이터를 동시에 수정하지 않을 것으로 가정, Lock을 설정하지 않는다
비관적 동시성 제어
select 적립포인트, 방문횟수, 최근방문일시, 구매실적 from 고객
where 고객번호 = :cust_num;
--새로운 적립포인트 계산
update 고객 set 적립포인트 = :적립포인트 where 고객번호 = :cust_num
- 적립포인트를 계산하는 동안, 다른 트랜잭션이 같은 고객의 실적정보를 변경한다면 문제가 생길수 있다
- 하지만 아래와 같이, SELECT 문에 FOR UPDATE를 사용하면 고객 레코드에 Lock을 설정함으로 데이터가 잘못 갱신되는 문제를 방지할 수 있다
select 적립포인트, 방문횟수, 최근방문일시, 구매실적 from 고객
where 고객번호 = :cust_num for update;
- 비관적 동시성 제어는 자칫 시스템 동시성을 심각하게 떨어뜨릴 우려가 있지만, FOR UPDATE에 WAIT 또는 NOWAIT 옵션을 함께 사용하면 Lock을 얻기 위해 무한정 기다리지 않아도 된다
6.4.3 채번 방식에 따른 INSERT 성능 비교
가장 중요하고 튜닝 요소가 많은 것은 INSERT 이다
신규 데이터를 입력하려면 PK 중복을 방지하기 위한 채번이 선행되어야 하는데, 가장 많이 사용하는 아래 세 가지 채번 방식의 성능과 장단점을 비교해보자
- 채번 테이블
- 사용자가 직접 한다
- 범용성이 좋다
- 다른 채번 방식에 비해 성능이 좋지 않다
- 로우 Lock 경합 때문
- 동시 Insert 가 아주 많은 테이블에는 사실상 이 방식을 사용하기 어렵다
- 시퀀스 오브젝트 - 웬만하면 이걸 쓰자!
- 오라클이 한다
- 성능이 빠르다
- 시퀀스 Lock에 의한 성능 이슈가 있지만, 캐시 사이즈를 적절히 설정하면 가장 빠른 성능을 제공한다
- MAX +1 조회
- Select에서 제일 큰 값 + 1
- 같은 값을 얻게 되면 Insert 문은 둘 중 하나만 성공하게 된다 → 다른 값을 얻을때까지 다른 한 사람이 Max + 1을 계속 돌린다
- 이런 이유 때문에 시퀀스 오브젝트를 쓰라는 것이다 → 시퀀스도 안되면 Table을 쓰자
채번방식 | 식별자 구조 | 주요 경합 | 부수적인 경합 | 비고 |
채번 테이블 | 일련번호 | (값 변경을 위한) 로우 Lock 경합 |
(동시성이 높다면) 채번 테이블 블록 경합 |
- 채번 테이블 관리 부담 (내가 직접 관리) |
구분 + 순번 | 단일 일렵번호일 때보다 Lock 경합 감소 | |||
시퀀스 오브젝트 | 일련번호 | 시퀀스 경합 | (시퀀스 경합 해소 시) 인덱스 블록 경합 |
- 시퀀스 관리 부담 (큰 부담은 아니다) - Insert 과정에 결번 가능성 |
MAX + 1 | 일련번호 | (입력 값 중복 시) 로우 Lock + 재실행 |
(동시성이 매우 높다면) 인덱스 블록 경합 |
- 별도 오브젝트 관리 없음 - 중복 값 발생에 대비한 예외처리 필수(프로그래머가 코드로 예외처리) - PK 인덱스 구성에 따른 성능 차이 발생 |
구분 + 순번 | 단일 일련번호일 때보다 Lock 경합 감소 (구분 속성 값의 종류 수가 많으면, 현저히 감소) |
'SQL 튜닝 > CH06 DML 튜닝' 카테고리의 다른 글
파티션을 활용한 DML 튜닝(3) (0) | 2024.11.18 |
---|---|
Direct Path I/O 활용 (2) (0) | 2024.11.18 |
기본 DML 튜닝 (1) (1) | 2024.11.17 |