[TIL] 트랜잭션 - 동시성 제어

sooyoung choi·2024년 1월 1일
0

CS

목록 보기
2/21
post-thumbnail

트랜잭션

  • 데이터 다룰 때 장애가 일어난 경우 데이터를 복구하는 작업의 단위가 된다.
  • 여러 작업이 동시에 같은 데이터를 다룰 때 이 작업들을 서로 분리하는 단위가 된다.

수행 과정



동시성 제어(Currency Control)

  • 공연 예매 시 좌석 선택에 있어서 사용자끼리 동시에 같은 좌석을 선택했을 때, 한 사람만 좌석이 예매 되어야 하고 남은 한 사람은 예매가 되지 않아야 한다.
  • 여러 유저의 동시 접속 문제는 모든 서비스에서 일어날 수 있는 문제
  • 동시성을 제어할 수 있도록 LOCK 기능과 SET TRANSACTION 사용하여 트랜잭션의 격리성 수준을 조정할 수 있다.


트랜잭션 격리 수준

  • 여러 트랜잭션들이 동시에 처리될 때 트랜잭션끼리 얼마나 고립되어 있는 지를 나타내는 것
  • 격리 수준에 따라 특정 트랜잭션이 다른 트랜잭션에서 변경한 데이터를 볼 수 있도록 허용할 지 말 지를 결정할 수 있다. 모두 LOCK 걸어버리면 동시에 수행되었던 트랜잭션들은 순차적으로 수행될 수 밖에 없으니 성능은 떨어지게 된다. 가장 효율적인 LOCKING 방법을 고민해야 한다.

Lock 종류

  1. Shared Lock 공유 락
  • 데이터 읽을 때 사용되는 락, 공유 락끼리 동시 접근 가능하다.
  1. Exclusive Lock 베타 락
  • 데이터 변경할 때 사용되는 락
  • 트랜잭션이 완료될 때까지 유지되며 해당 락이 해제되기 전까지 다른 트랜잭션 접근이 금지된다.

격리수준 0 - Read uncommitted

  • 트랜잭션 처리중에 읽는 것이 허용된다
  • 아직 커밋되지 않은 데이터를 다른 트랜잭션이 읽을 수 있다.
  • 데이터 읽는 동안 해당 데이터에 공유 락이 걸리지 않는 계층이다.

문제점 Dirty Read

1번 A 계좌로 송금, 아직 커밋 전
2번 A계좌의 송금 후 금액 조회
-> 계좌 송금 중 롤백이 일어났을 때, 1번은 여전히 이전 금액이지만 2번은 송금 후 금액 조회된다.



격리수준 1 - Read committed

  • 하나의 트랜잭션이 처리되는 동안 다른 트랜잭션 접근할 수 없다. 커밋 후 가능
  • 데이터를 읽는 동안 해당 데이터에 공유 락이 걸리는 계층

문제점 Non-repeatable read

  • 한 트랜잭션이 처리되는 동안 특정 값을 조회할 때 다른 값이 조회되는 현상 REPEATABLE READ의 정합성에 어긋난다
  • 트랜잭션 1이 계좌를 조회했을 때 잔고가 10000원
  • 트랜잭션 2에서 A계좌로 송금을 완료해 커밋하여 잔고가 10000 → 20000원이 되었을 때
    -> 트랜잭션 1이 다시 잔고를 조회하면 10000원이 아니라 20000원이 된다.


격리수준 2 - Repeatable Read

  • 트랜잭션이 처리되는 동안 한 번 조회한 데이터의 내용이 항상 동일함을 보장한다.
    -> 다른 트랜잭션은 자신의 트랜잭션 번호보다 낮은 트랜잭션 번호의 처리가 끝나기 전까지 해당 데이터를 수정할 수 없다.
  • 한 트랜잭션이 완료될 때까지 SELECT 쿼리가 사용되는 모든 데이터에 공유 락이 걸리는 계층이다.
  • 데이터를 수정할 때는 Undo 공간에 백업해 두고 실제 레코드 값을 변경한다.
  • 백업 데이터는 불필요 하다고 판단되는 시점에 주기적으로 삭제한다.
  • 백업 레코드가 많아지면 성능이 저하될 수 있다.
  • 이러한 변경 방식을 MVCC(Multi Vercion Concurrency Control)이라 부른다.
  • 단점은 INSERT/DELETE문에 대한 정합성이 보장되지 않는다는 점이다

문제점: Phantom Read

  • 원래 있던 데이터가 사라지거나 혹은 생기는 현상이 발생할 수 있다.
  • 1번 트랜잭션이 특정 계좌에서 2억 원을 조회했었는데 2번 트랜잭션이 롤백하면 해당 데이터는 사라지기 때문이다.


격리수준 3 - Serializable

  • 가장 엄격한 격리 수준
  • 한 트랜잭션이 SELECT 쿼리를 실행해 테이블을 읽으면 다른 트랜잭션은 해당 테이블에 대한 추가, 변경 또는 삭제를 할 수 없다.

문제점: 성능 저하



동시성 문제 해결 방법


1. 비관적 동시성 제어

  • 시용자들이 같은 데이터를 동시에 수정할 것이라 가정한다.
  • 데이터를 읽는 시점에 Lock(Repeatable Read 또는 Serializable) 걸고, 트랜잭션이 완료될 때까지 Lock 유지
  • SELECT 시점에 Lock 걸기 때문에 심각한 성능 저하 초래 가능, wait, nowait 옵션과 함께 사용할 필요가 있다.

2. 낙관적 동시성 제어

  • 사용자들이 같은 데이터를 동시에 수정하지 않을 것이라 가정한다.
  • 데이터를 읽는 시점에 Lock 걸지 않으며, 수정 시점에 값이 변경 됐는지를 검사한다.

0개의 댓글