프로그래밍/DB

트랜잭션 이해 2 - 격리, 단계, 수준

Baesj 2021. 9. 7. 14:07

같은 데이터에 동시 접근

 

경쟁 상태(Race Condition)

 - 여러 클라이언트가 같은 데이터에 접근할 때 문제 발생

 

트랜잭션 격리(Isolation)

 - 트랜잭션을 서로 격리해서 다른 트랜잭션이 영향을 주지 못하게 함

 - 트랜잭션의 격리성은 일관성과 마찬가지로 Lock을 강하게 오래 유지할수록 강화되고, Lock을 최소화할수록 약화된다.

 

가장 쉬운 방법은 트랜잭션을 순서대로 실행

 1. 동시 접근 문제가 없음

 2. 하지만 한 번에 한 개 트랜잭션만 처리하므로 성능(처리향) 저하 가능

 

낮은 단계의 격리성 수준에서 발생할 수 있는 현상들

1. Dirty Read

 - 다른 트랜잭션에 의해 수정됐지만 아직 커밋되지 않은 데이터를 읽는 것을 말한다.

2. Non-Repeatable Read

 - 한 트랜잭션 내에서 같은 쿼리를 두 번 수행했는데, 그 사이에 다른 트랜잭션이 값을 수정 또는 삭제하는 바람에 두 쿼리 결과가 다르게 나타나는 현상을 말한다.

3. Phantom Read

 - 한 트랜잭션 내에서 같은 쿼리를 두번 수행했는데, 첫 번째 쿼리에 없던 유령 레코드가 두번째 쿼리에서 나타나는 현상을 말한다.

 

다양한 격리 수준 지원

1. Read Uncommitted - 거의 사용하지 않음

 - 트랜잭션에서 처링 중인 아직 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 것을 허용

2. Read Committed

 - 커밋되어 확정된 데이터만 다른 트랜잭션이 읽도록 허용함으로써 Dirty Read를 방지

3. Repeatable Read

 - 트랜잭션 내에서 쿼리를 두 번 이상 수행할 때, 첫 번째 쿼리에 있던 레코드가 사라지거나 값이 바뀌는 현상을 방지

 - 오라클에서 구현할려면 for update 구문 사용

4. Serializable

 - 트랜잭션 내에서 쿼리를 두번 이상 수행할 때, 첫 번째 쿼리에 있던 레코드가 사라지거나 값이 바뀌지 않음은 물론 새로운 레코드가 나타나지도 않음

 

대부분의 DBMS가 Read Committed를 기본 트랜잭션 격리성 수준으로 책택하고 있으므로 Dirty Read가 발생할 걱정은 안해도된다.

 

동시성 관련 다양한 문제들

1. 커밋되지 않은 데이터 읽기 - dirty read

2. 커밋되지 않은 데이터 덮어쓰기 - dirty write

Read Committed

- 커밋된 데이터만 읽기

  - 커밋된 값과 트랜잭션 진행 중인 값을 따로 보관

- 커밋된 데이터만 덮어쓰기

  - 행 단위 잠금 사용(Lock 사용)

    - 같은 데이터를 수정한 트랜잭션이 끝날 때까지 대기

 

3. 읽는 동안 데이터 변경 1 - read skew

Repeatable Read

- 트랜잭션 동안 같은 데이터를 읽게 함

  - 구현 예 : MVCC(Multi-Version Concurrency Control) - 스냅샷 격리성 수준(Snapshot Isolation Level)이라고도 불림

    - 읽는 시점에 특정 버전에 해당하는 데이터만 읽음

 

4. 변경 유실 - Lost Update - 같은 데이터를 쓸 때 발생

변경 유실에 대한 몇 가지 처리 방법

- 원자적 연산 사용 - DB가 지원하는지 확인필요

 - DB가 지원하는 원자적 연산 사용

 : 동시 수정 요청에 대해 DB가 순차 처리

2. 명시적인 잠금

 - 조회할 때 수정할 행을 미리 잠금

3. CAS(Compare And Set)

 - 수정할 때 값이 같은지 비교

 

5. 읽는 동안 데이터 변경 2

Serializable

 - 인덱스 잠금이나 조건 기반 잠금 등 사용

 

동시성 제어가 어려운 이유

동시성과 일관성은 트레이드 오프 관계인 것

즉, 동시성을 높이려고 Lock의 사용을 최소화하면 일관성을 유지하기 어렵고, 일관성을 높이려고 Lock을 적극적으로 사용하면 동시성이 저하된다.

 

동시성 제어

비관적 동시성 제어

 - 데이터를 읽는 시점에 Lock을 걸고 트랜잭션이 완료될 때까지 이를 유지한다.

낙관적 동시성 제어

 - 데이터를 읽을 때는 Lock을 설정하지 않는다. 대신 수정 시점에 , 다른 사용자에 의해 값이 변경됐는지를 반드시 검사해야한다.

   - select 할 때 값을 가지고 있다가, 수정 시점에 where 조건에서 비교한다.(최종 변경일시 칼럼을 사용하면 간단하게 할 수 있다)

 

 

정리

동시성은 초보자가 놓치기 쉬운 문제

 - 동시성 문제와 격리 수준을 이해하면 문제 발생을 줄일 수 있음

잠금 시간은 최소화

 - 잠금시간이 길어지면 성능(처리량) 저하

동시성 문제를 다룰 때는 다음을 알면 좋음

 - 사용하는 DB의 기본 격리 레벨

 - DB의 격리 레벨 동작 방식(DB마다 동작 방식이 다를 수 있음)

 

 

참고

사이트 : https://www.youtube.com/watch?v=poyjLx-LOEU

도서 : SQL 전문가 가이드 - 한국 데이터 진흥원