DB 동시성 제어 & 교착상태
DB : 동시성 제어
DB 트랜잭션의 동시성 제어
란 여러 트랜잭션이 작업을 성공적으로 마칠 수 있도록 트랜잭션의 실행 순서를 제어하는 기법이다.
동시성 제어가 필요한 이유
동시성
이 높을수록 DB의 성능이 좋다. 하지만 데이터 일관성
이 깨질 수 있기 때문에 동시성 제어가 필요하다.
Trade-Off관계에 있는 동시성과 데이터 일관성은 격리수준으로 제어할 수 있다.
트랜잭션간에 동시성 제어를 하지 않을 경우 발생하는 문제점
Lost Update
하나의 트랜잭션이 갱신한 내용을 다른 트랜잭션이 덮어씀으로써 갱신이 무효화되는 문제
Inconsistency
데이터에 update 연산이 수행되는 도중 한 트랜잭션은 update 전의 데이터를 읽고, 다른 트랜잭션은 update 이후의 데이터를 읽어서 발생하는 데이터 불일치 문제
Cascading Rollback
트랜잭션1이 데이터를 update하는 중간에 트랜잭션2가 해당 데이터를 읽고 commit한 경우, 트랜잭션1이 rollback한다면 트랜잭션2는 rollback하지 못하는 문제(이미 commit되었기 때문)
Incorrect Summary
특정 레코드에 집계함수를 적용하는 동안 다른 트랜잭션이 집계 예정인 데이터를 수정하여 부정확한 집계 결과를 얻는 문제
Dirty Read
⭐커밋되지 않는 트랜잭션의 데이터 변경사항을 볼 경우, 무효가 된 데이터를 읽어 발생하는 문제 (Inconsistency와 다름)
Non-Repeatable Read
⭐한 트랜잭션에서 같은 쿼리를 두번 수행할 때, 동일한 결과가 나오지 않는 문제
Phantom Read
⭐일정 범위의 레코드를 두번 이상 읽었을 때, 이전에 없던 레코드가 나타나는 현상
Update 부정합
트랜잭션은 update 구문을 실행할 때 실제 레코드가 아닌 Undo 세그먼트 영역에서 실행한다.
트랜잭션1이
name=hjoon
인 행을 읽는다. →ok
트랜잭션2가 name=hjoon인 행의 name 속성을 top으로 변경하고 commit한다
undo 세그먼트 영역의 데이터에 x-lock을 걸 수 없다. → 따라서 실제 레코드에 x-lock을 건다.
변경을 마치고 commit되면 실제 레코드에 변경 사항이 반영된다
→
ok
(실제 레코드에 name=hjoon인 행은 없고 name=top인 행만 존재한다.)
트랜잭션1이
name=hjoon
인 행의 name 속성을 sun으로 변경하려 한다.undo 세그먼트 영역의 데이터에 x-lock을 걸 수 없다 → 실제 레코드에 x-lock을 걸려고 시도한다.
하지만 실제 레코드에 name=hjoon인 행이 존재하지 않는다.
→
0 row(s) affected
(실제 레코드에 아무런 변경이 일어나지 않음)
DB 트랜잭션의 동시성 제어 방법
Locking
⭐ : 트랜잭션이 데이터에 Lock을 설정하면 다른 트랜잭션은 Lock이 걸린 데이터가 Unlock될 때까지 접근, 수정, 삭제하지 못하도록 하는 제어 기법Timestamp
: Timestamp(시스템에서 생성되는 고유 번호)를 트랜잭션에 부여하여 트랜잭션 접근 순서를 미리 정하는 제어 기법먼저 들어온(Timestamp가 더 빠른) 트랜잭션이 먼저 수행됨
Validation 검증
: 트랜잭션을 먼저 수행하고 트랜잭션이 종료될 때 적합성을 검증하여 DB에 최종 반영하는 제어 기법각 트랜잭션은 메모리 상의 DB 복사본에서 연산을 수행하고 종료 시에 적합성 검증 후 DB에 최종 반영됨
DB : Lock
DB Lock의 종류
Shared Lock(S-Lock)
: 데이터에 읽기 연산을 수행할 때 설정하는 Lock"S-Lock이 걸린 데이터에 다른 트랜잭션이 S-Lock을 걸 수 있고, X-Lock은 걸 수 없다"
Select 쿼리를 수행하는 트랜잭션이 데이터에 S-Lock을 걸면 다른 트랜잭션들은 데이터를 읽을(Select) 순 있지만 변경(Update, Delete)할 수 없다.
Exclusive Lock(X-Lock)
: 데이터에 쓰기 연산을 수행할 때 설정하는 Lock"X-Lock이 걸린 데이터에 다른 트랜잭션은 S-Lock, X-Lock을 걸 수 없다"
하나의 트랜잭션이 데이터에 X-Lock을 걸면, 트랜잭션이 종료될 때까지 X-Lock이 유지된다.
Update, Delete쿼리를 수행하는 트랜잭션이 데이터에 X-Lock을 걸면 다른 트랜잭션들은 데이터를 읽을 수도 변경할 수도 없다
DB Lock의 단위
Row Level
: 테이블 행에 Lock을 설정Column Level
: 테이블 열에 Lock을 설정(Column Lock 해제 시 많은 리소스가 소모되어 잘 사용 안됨)Page Level
: 같은 Page에 존재하는 모든 Row에 Lock을 설정(Page : SQL Server의 기본 IO 단위)Table Level
: Table과 Index에 Lock을 설정 (DDL Lock이라고 불리기도 함)Database Level
: 데이터베이스 복구, 스키마 변경시 설정되는 Lock
DB : Blocking
DB에서 하나의 데이터에 Lock을 걸려는 트랜잭션간에 Race Condition이 발생한 경우, 특정 트랜잭션이 작업을 진행하지 못하게 막은 상태를 Blocking
이라고 한다.
데이터의 고유성을 보장하기 위해 Blocking으로 트랜잭션의 개입을 잠시 막는다.
DB Blocking 예시
S-Lock이 설정된 데이터를 Read하려는 트랜잭션은 Blocking 되지 않는다. (
S-Lock 👈 S-Lock
)S-Lock이 설정된 데이터를 Update, Delete하려는 트랜잭션은 Blocking 된다. (
S-Lock 👈 X-Lock
)X-Lock이 설정된 데이터를 Read, Update, Delete하려는 트랜잭션은 Blocking 된다. (
X-Lock 👈 S-Lock 또는 X-Lock 👈 X-Lock
)
DB Blocking을 피하는 방법
트랜잭션 수행 시간을 짧게 설정하여 Race Condition 발생 가능성을 낮춘다.
적절한 쿼리 튜닝을 한다. (쿼리 수행시간이 길면 트랜잭션 수행 시간도 길어지기 떄문)
동일한 데이터를 변경하는 트랜잭션이 동시에 수행되지 않도록 설계한다
트랜잭션 격리수준을 필요이상으로 상향 조정하지 않는다.
DB : Dead Lock
DB 트랜잭션 간에 발생하는 교착 상태
란 서로 다른 두 트랜잭션이 각자 데이터에 Lock을 걸어두고, 서로의 데이터에 접근하기 위해 Unlock될 때까지 무한정 대기하는 상태이다.
예시
트랜잭션1과 2는 각자 접근하려는 데이터가 Unlock되기를 기다리기 때문에 Blocking 상태가 된다. 결국 트랜잭션1과 2는 다음 연산(쿼리)을 진행하지 못한 채 무한정 대기 상태에 빠진다.
참고 예시
트랜잭션2는 트랜잭션1이 S-Lock을 해제할 때까지 무한정 대기 해야함
DB Dead Lock 해결 방안
DB Dead Lock이 감지되면 둘 중 하나의 트랜잭션을 강제로 종료시킨다.
트랜잭션간의 접근 순서 규칙을 정한다.
DB Blocking vs DB Dead Lock
DB Blocking | DB Dead Lock |
---|---|
Blocking된 트랜잭션은 목적 데이터에 Lock이 풀리면 Blocking 상태에서 벗어난다. | 두 트랜잭션이 서로에 의해 Blocking 되었으므로 그 누구도 먼저 Blocking 상태에서 벗어나지 못한다. 결국 무한정 대기 상태에 빠진다. |
Last updated