Transaction 정리(정리중)

Developer:Bird·2021년 12월 12일
0

정의: 데이터베이스 관리 시스템 또는 유사한 시스템에서 상호작용의 단위이다.
이때 트랜잭션은 하나의 쿼리를 날리는것을 의미하지는 않는다. 실제 db에 해당하는 계산을 한번에 Commit(DATABASE에 영향을 끼침)시키는것을 말한다.
그림과 같이 하나의 트랜잭션에 여러 쿼리수행이 일어날 수 있고, 하나의 쿼리수행 시마다 실제 DB에 영향을 끼치지않는다.

ACID

ACID는 트랜잭션의 특성이다.

A: Atomicity(원자성)

트랜잭션은 여러 쿼리로 이루어 질 수 있다고 했는데 그중 몇개는 실패할시 디비에 commit하기 보다는, 하나라도 실패시 롤백시키는 특성을 말한다. 즉 All or Nothing이다. 변경적용중 오류가 날 경우 롤백을 시키는 의미에서 Atomicity이라는 단어보다는 Abortability도 괜찮아 보인다.

C: Consistency(일관성)

트랜잭션이 성공시 언제나 일관성 있는 데이터베이스 상태를 유지하는 것을 말한다.쉽게 말해서 트랜잭션 이후 데이터의 손실이나 변형이 일어나지 않음을 의미한다.

I: Isolation(격리성)

트랜잭션 수행시 다른 트랜잭션의 작업이 간섭할 수 없고, 항상 독립적이다.

D: Durability(지속성)

commit한 상태에 관해서는 영원히 보장된다.

ISOLATION

트랜잭션의 격리수준에 관해서 성능과 어플리케이션의 특성에 따라서 설정 할 수 있다. 이때 ISOLATION을 완벽하게 이해하기 위해서는 MVCC와 LOCK에 관해서 이해를 해야한다. 그 이유는 (Multi Version Concurrency Control) MODE를 사용할지 안할지에 따라서 다르게 작동하게 되는데 ORACLE의 경우 default로 False로 돼 있다. False일 경우 LOCK이 사용된다. LOCK에 대해 간단하게 설명 하자면 다음과 같다.

참고
READ LOCK(읽기 잠금): 읽기시에 잠금이다. 공유 잠금이라고 하며, 쓰기 잠금이 없을시에 읽는게 가능하다.
WRITE LOCK(쓰기 잠금): INSERT, UPDATE와 같이 행에 변화를 끼칠때 생기는 LOCK이며, 읽을려는 테이블 또는 행에 관해서 다른 쓰기 잠금이 없을시에 걸 수 있으며, 이를 걸게 되면 다른 트랜잭션에서는 기다려야 한다.

다음과 같이 LOCK을 걸게되면 동시성에 심각한 문제를 끼칠 수 있다. 쓰기잠금을 사용하고 있는 트랜잭션이 있을경우 다른 트랜잭션의 실행은 블록되기 때문이다. 따라서 MVCC를 선호한다. MVCC의 경우 트랜잭션이 수행될때마다 수행시점의 데이터에 대한 스냅샷을 찍고 변경되는 내용마다 version을 매겨서 UNDO LOG에 기록하는 방식이다. MVCC에 대한 내용은 다른장에서 다뤄보도록 하자.
LOCK 방식과 MVCC방식 두가지 개념을 바탕으로 Isolation level에 대해서 공부해보자. 이때 MVCC의 경우 MYSQL, ORACLE, POSTGRESS SQL마다 다르게 작동을 하는데 POSTGRESS SQL을 기준으로 설명함을 참고하길 바란다.

- READ UNCOMMITED

0. 특징

DIRTY READ, Non-Repeatable Read, Phandom Read 같은 문제가 생길 수 있다.

1. LOCK

트랜잭션이 수행 될때, 다른 트랜잭션에 수행되는 아직 커밋되지 않은 값들도 읽을 수 있는 상태이다. 즉 아무런 잠금도 없는 상황이다.

2. MVCC

위 경우는 UNDO LOG를 사용하지 않는 방식으로 작동된다.

3. 예시

다음과 같이 트랜잭션2과 읽어야하는 시점의 테이블에는 부산이 없었지만, DIRTY READ의 읽기로 인해서 조회가 됐다. 만약 트랜잭션1이 성공적으로 커밋이 될것을 보장한다면, 크게 문제가 없을것이라고 생각 할 수 도 있지만, 만약 트랜잭션1 이 중간에 실패가 해서 롤백이 되게 된다면 트랜잭션2에서는 실제 존재하지 않는 데이터를 SELECT하게 되는 문제가 생길 수 있고, 돈 거래와 같은 민감한 주제에 관해서는 더 큰 정합성의 문제를 일으킬 수 있을것같다. 따라서 락비용이 발생 하지 않아 동시성 측면에서 속도적으로 이득을 볼 수 있지만 지양해야하는 격리수준이다.

- READ COMMITTED

  1. common
    이는 커밋된 데이터만 읽을 수 있도록 해준다. 따라서 DIRTY READ의 문제가 해결 될 수 있다. 다만 이또한 Non-Repeatable Read, Phandom Read 와 같은정합성에 문제를 일으 킬 수 있다

  2. Lock
    이 격리 수준의 경우 트랜잭션에 있는 쿼리들을 수행할때, 읽기 잠금을 수행하며, 다른 쓰기 잠금이 풀릴때까지 기다려야 한다.

  3. MVCC
    트랜잭션 시점에 읽는 데이터의 정보가 변경이 됐으면, UNDO LOG로 부터 CR(일관된 읽기)를 만든다.

    처음에 222를 기준으로 조회했을때 BUSAN이 나왔는데, 또하나의 트랜잭션에서 한번더 SELECT을 하니 JEJU가 나왔다. 즉 정합성에서 문제가 발생했다. 실무적인 관점에 봤을때 트랜잭션에서 실행하는 쿼리의 단위를 적게 가져가면 충분히 이러한 정합성의 문제를 해결 할 수 있지 않을까? 트랜잭션을 작은 단위로 가져갔을때의 문제점은 잦은 디비접근과 변화라고 생각하는데 벤치마킹을 해서 TPS를 측정한 후, 쿼리의 단위에 관해 최적화하여 사용하면 충분히 괜찮을것 같다는 생각이다.

- REPEATABLE READ:

이 격리 수준의 경우, 트랜잭션 시작시점의 버퍼에 있는 행에 관해서 읽기,쓰기 잠금이 걸리는 상황이다. 따라서 쓰기잠금이 있을 시 기다려야 한다. 이로인해서 Non-Repeatable Read를 해결할 수 있다. 하지만 테이블 레벨에서 쓰기 잠금이 걸려있는 상황은 아니라서 트랜잭션 중간에 새로운 행이 추가되는 Phandom Read가 발생할 수 있다.

https://www.slideshare.net/pgday_seoul/mvcc-in-postgre

profile
끈임없이 발전하자.

0개의 댓글