Database Transaction

홍준식·2024년 7월 28일

트랜잭션 격리 수준이란 동시에 실행되는 트랜잭션들이 서로 간섭하지 않도록 하기 위해 설정하는 규칙입니다.
격리 수준이 높을수록 트랜잭션 간 고립 수준이 높아지고 트랜잭션간 문제가 발생하지 않지만 그만큼 성능이 낮아진다는 문제가 있습니다.

트랜잭션 격리 수준은 일반적으로 Read Uncommitted, Read Committed, Repeatable Read, 그리고 Serializable로 구분됩니다.

Read Uncommitted

가장 낮은 격리 수준으로 트랜잭션이 커밋되지 않은 데이터도 다른 트랜잭션에서 읽을 수 있습니다.

락을 통한 트랜잭션간 격리가 없어 성능이 뛰어나고 성능이 뛰어나고 병렬 처리 효율이 높습니다.

하지만 트랜잭션 A가 아직 커밋하지 않은 데이터를 트랜잭션 B가 읽을 수 있지만 트랜잭션 A가 롤백되면 B는 잘못된 데이터를 읽는 dirty read 발생하게 됩니다.

Read Committed

Read Uncommitted의 dirty read를 해결하는 격리 수준입니다.
트랜잭션이 커밋된 데이터만 읽을 수 있도록 하는 방식입니다.

트랜잭션 A가 데이터를 읽고 나서 트랜잭션 B가 데이터를 변경하고 커밋하면 트랜잭션 A가 다시 읽을 때 다른 데이터를 읽는 Non-repeatable Read 문제가 발생할 수 있습니다.

일반적으로 오라클과 Postgresql 등 많은 데이터베이스에서는 격리 수준 기본값으로 Read Committed를 사용합니다.

Repeatable Read

Non-repeatable Read 문제를 해결하는 방법으로 트랜잭션이 시작된 후 읽은 데이터는 트랜잭션이 끝날 때까지 변경되지 않도록 하는 기법입니다.

트랜잭션은 자신의 트랜잭션 번호보다 낮은 트랜잭션에서 변경된 데이터만을 읽어들일 수 있게 하는 방법으로 DBMS는 변경 전의 데이터를 Undo 영역에 백업해두고 트랜잭션은 Undo 영역을 통해 자신보다 작은 트랜잭션 id를 갖는 데이터를 가져와 읽어들입니다.

하지만 트랜잭션이 같은 쿼리를 두 번 수행할 때, 중간에 다른 트랜잭션이 데이터를 삽입하면 결과 집합이 달라질 수 있는 phantom read가 발생할 수 있습니다.

일반적으로 MySQL InnoDB의 기본 설정입니다.

Serializable

가장 높은 격리 수준으로 트랜잭션을 거의 병렬처리하지 않고 직렬로 처리하는 것처럼 동작하게 됩니다.

이를 통해 모든 종류의 문제가 발생하지 않지만 성능이 많이 떨어지게 됩니다.

0개의 댓글