[database] transaction-isolation level

EMMA·2022년 5월 1일
0

Transaction - isolation level에 대하여


Introduction

프로젝트 할 당시에, get_or_create 함수를 사용하면서 transaction에 대해 잠깐 찍먹(?)을 했었다.

transaction이라 하면,

  • 업무 처리의 가장 기본 단위, commit(연산)되거나 rollback(철회)됨
  • 4가지 특성을 갖는다: atomictiy, consistency, isolation, durability

ACID 관련해서는 지난 글 참고.

이미지 출처: 해시넷 - 트랜잭션의 상태


Isolation level

Transactions specify an isolation level that defines how one transaction is isolated from other transactions.
(출처: Microsoft - Understanding isolation levels)

Isolation level은 여러 transcation이 진행될 때, 그들끼리 얼마나 고립되어 있는가 = 어느 수준까지 transaction 원칙을 보장하는가를 결정하는 것이다.

ACID 원칙을 엄격하게 지키다보면, concurrency 성능이 떨어지기 때문에 level 별로 side effect 허용 수준을 정한 것.

이미지 출처: Microsoft

level 별 발생하는 현상에 대해 먼저 짚고 넘어가자.

  • Dirty Read: 한 transaction 상에서 변경되었으나 commit은 되지 않은 데이터를 다른 transaction에서 읽는 현상
  • Non-repeatable Read: 한 transaction이 특정 row를 read할 때, 다른 transaction에 의해 내용이 update/delete -> commit 되어 일관성을 guarantee 할 수 없는 현상
  • Phantom Read: 한 transaction이 일정 범위의 데이터를 여러 번 read할 때, 다른 transaction에 의해 새로운 데이터가 insert 되거나 rollback되어 해당 데이터가 read되기도, 안되기도 하는 현상

아.. 자꾸 phantom read가 phantom thread로 읽혀...

이미지 출처: https://ko.cm-ob.pt/is-phantom-thread-based-true-story

level 3 - Serializable

가장 높은 Isolation level로, read/write/range locks가 요구된다. 중간에 새로운 데이터가 insert되는 것도 막는다.

  • read lock: shared lock이라고도 하며 읽을 수는 있지만 update/delete는 할 수 없는 상태로 만드는 것
  • write lock: exclusive lock이라고도 하며 다른 transaction은 read/update/delete 모두 할 수 없고 대기상태로 빠짐
  • range lock: gap lock이라고도 하며 데이터 범위에 걸려지는 lock. 예를 들어, select ... where id between 10 and 20 의 조건으로 한 transaction이 쿼리를 진행할 때, 해당 범위에 exclusive lock이 걸려 다른 transaction이 id=15에 해당하는 데이터를 insert하지 못하고 대기 상태에 빠짐

그래서 dirty read/non-repeatable read/phantom read의 문제가 발생하지 않으나 dead lock 상태에 놓일 수 있다.

  • deak lock: 교착 상태, 즉 2개 이상의 transaction이 같은 데이터(row)에 lock을 걸어버려 서로의 작업이 끝나기를 기다리게 되는 상태. 결과적으로 모두 실행되지 못하고 timeout되어 버린다.

뿐만 아니라, concurrency 기능이 떨어질 수 있다.


level 2 - Repeatable Read

한 transaction 내에서 여러 번 데이터를 읽어도 데이터가 변하지 않음을 보장하는 level.
(read/write lock 사용)
1번 transaction이 읽은 데이터는 해당 transaction이 종료될 때까지 갱신/삭제를 allow하지 않는다.

하지만 다른 transaction에 의해 새로 insert된 데이터가 생겨버리는 phantom read는 막지 못한다.
(range lock 사용x)


level 1 - Read committed
commit 된 데이터만 읽을 수 있도록 허용하는 level.

Dirty read는 방지할 수 있으나, non-repeatable read/phantom read는 막을 수 없다. 그래서 한 transaction 에서 데이터를 여러 번 read할 때, 데이터의 일관성은 보장할 수 없다.

level 0 - Read uncommitted
commit되지 않은 데이터까지 읽을 수 있도록 허용하는 level.
따라서 Dirty read/Non-repeatble read/phantom read를 막을 수 없고, 최종적으로 rollback될 수도 있는 데이터까지 읽을 수 있는 위험이 있다.


그래서, 어떤 level이 가장 좋은거야?

우선 Microsoft 문서를 보면, 최소 Repeatable read 는 적용해야 한다고 되어 있다.

Transactions must be run at an isolation level of at least repeatable read to prevent lost updates that can occur when two transactions each retrieve the same row.

Serializable 단계까지 적용하면 언급된 이슈들은 최소화할 수 있겠지만 동시처리 기능이 매우 저하되므로, 그래서 문서들에 설명된 것처럼 Repeatable read를 필요한 경우에만 Serializable까지 적용하는 것 같다.

데이터베이스 종류에 따라, lock은 걸지 않아도 특정 시점을 제외한 변경 사항은 모두 무시하여 데이터 일관성을 유지하는 설정 등이 제공되기도 한다고 한다.


참고 자료
https://docs.microsoft.com/en-us/sql/connect/jdbc/understanding-isolation-levels?view=sql-server-ver15
https://en.wikipedia.org/wiki/Isolation_(database_systems)#Isolation_levels
https://www.geeksforgeeks.org/transaction-isolation-levels-dbms/
https://www.letmecompile.com/mysql-innodb-lock-deadlock/

profile
예비 개발자의 기술 블로그 | explore, explore and explore

0개의 댓글