트랜잭션과 격리수준, MVCC

2022. 11. 12. 04:09Database/DB 접근 기술

몇 주 전 Real MySQL을 공부하며 정리했던 내용을 팀원들에게 공유한 적 있다.
오늘 들은 스프링 수업에서 이를 다루어서, 노션 페이지에 있는 포스팅을 블로그에 옮긴다.

트랜잭션

  • 트랜잭션은 작업의 완전성을 보장해 준다.
    • 논리적인 작업 셋을 모두 완벽하게 처리하거나, 처리하지 못 할 경우에는 원 상태로 복구해 작업의 일부만 적용되는 현상(Partial Update)이 발생하지 않게 만들어준다.
  • 잠금과 트랜잭션은 비슷한 개념 같지만, 잠금은 동시성을 제어하는 기능이며 트랜잭션은 데이터 정합성을 보장

  • 트랜잭션은 DBMS의 커넥션과 마찬가지로 최소의 코드에만 적용하는 것이 좋다.
    • 트랜잭션의 범위를 최소화하라!
  • 특히, 네트워크 작업 등 긴 시간이 걸리는 작업은 제외해야 한다.
    • 메일 전송, 파일 전송 등 외부 서버와 통신하는 작업을 트랜잭션에 포함하면, 외부 서버에 문제가 발생할 경우 DBMS 서버 또한 문제가 발생할 수 있다.

격리수준

여러 트랜잭션이 동시에 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있게 허용할지 말지 결정함

READ UNCOMMITTED (커밋되지 않은 읽기)

각 트랜잭션의 변경 내용이 commit이나 rollback 여부에 상관 없이 다른 트랜잭션에서 보임

READ COMMITTED (커밋된 읽기)

어떤 트랜잭션에서 데이터를 변경했더라도 commit이 완료된 데이터만 다른 트랜잭션에서 조회 가능

테이블 데이터 ⇒ (’한국’, ‘서울')

[A 세션] 트랜잭션 시작

[A 세션] 데이터 변경 (‘한국’, ‘서울’) → (’한국’, ‘경기’)

[B 세션] 트랜잭션 시작 

[B 세션] 조회: (’한국’, ‘서울’)

[A 세션] 커밋

[B 세션] 조회: (’한국’, ‘경기’)

⇒ 하지만 한 트랜잭션 내에서 같은 쿼리문이 실행되었음에도 불구하고 조회 결과가 다른 문제 (Phantom read)

REPEATABLE READ (반복 가능한 읽기) - MySQL

InnoDB 스토리지 엔진은 트랜잭션이 Rollback 될 가능성에 대비해 변경되기 전 레코드를 언두 공간에 백업해두고 실제 레코드 값 변경

이러한 변경 방식을 MVCC라고하며, 언두 영역에 백업된 이전 데이터를 이용해 동일 트랜잭션 내에서는 동일한 결과를 보여줄 수 있게 보장

MVCC란?

더보기

잠금 없는 일관된 읽기(MVCC, 다중 버전 동시성 제어)

 

  • InnoDB에서는 격리 수준이 SERIALIZABLE이 아닌 경우 MVCC 기술을 이용해 락을 걸지 않고 읽기 작업을 수행한다.
    (격리 수준이 SERIALIZABLE의 경우에는 순수한 읽기 작업의 경우에도 락을 필요로 한다).
  • 그림의 변경 트랜잭션이 다른 사용자의 SELECT 작업을 방해하지 않는다. InnoDB에서는 언두 로그에 있는 백업된 데이터를 사용하기 때문이다.
  • 트랜잭션이 길어지는 경우 언두 로그에 저장된 데이터가 쌓이므로 MySQL 서버가 느려질 수 있다. 따라서 가능한 한 빨리 트랜잭션을 완료하는 것이 좋다.

MySQL의 innodb 스토리지 엔진이 Repetable Read 수준에서 MVCC가 가능한 이유는, 넥스트 키 락 덕분이다.
하지만 이와 관련된 내용은 이번 포스팅에서 다루지 않는다.

SERIALIZABLE (직렬화 가능)

트랜잭션의 격리 수준이 SERIALIZABLE로 설정되면 읽기 작업도 공유 잠금(읽기 잠금)을 획득해야 하며, 동시에 다른 트랜잭션은 그러한 레코드를 변경할 수 없음.

즉, 한 트랜잭션에서 읽고 쓰는 레코드를 다른 트랜잭션에서는 절대 접근할 수 없음