[DB] 트랜잭션 격리 수준
서론
트랜잭션에 대한 개념과 특징, 상태에 대해 지난 포스팅에서 알아보았다.
트랜잭션의 특징 중 I에 해당하는 isolation(격리성)은 트랜잭션 수행 시에 서로 끼어들면 안된다는 것을 말한다.
데이터베이스는 여러 사용자가 같은 데이터에 접근할 수 있어야 한다. 순차적으로 접근할 수 있다면 쉽게 구현할 수 있겠지만 성능이 나쁠 것이다.
트랜잭션 격리 수준이란?
트랜잭션 격리 수준은 ‘여러 트랜잭션이 동시에 처리될 때 특정 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있게 허용할지 말지’를 결정하는 정도이다.
격리 수준은 READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE의 4가지로 나뉘며, 차례대로 뒤로 갈수록 트랜잭션 간의 데이터 격리 정도가 높아지며, 동시 처리 성능이 떨어진다.
각 격리 수준 별로 생기는 문제점
- DIRTY READ
- 커밋되지 않은 수정 중인 데이터를 다른 트랜잭션에서 읽을 수 있도록 허용할 때 발생하는 현상
- 어떤 트랜잭션에서 아직 실행이 끝난지 않은 다른 트랜잭션에 의한 변경 사항을 보게 되는 되는 경우
- NON-REPEATABLE READ
- 한 트랜잭션에서 같은 쿼리를 두 번 수행할 때, 두 쿼리의 결과가 상이하게 나타나는 비 일관성 현상
- 한 트랜잭션이 수행중일 때 다른 트랜잭션이 값을 수정 또는 삭제함으로써 나타난다.
- PHANTOM READ
- 한 트랜잭션에서 같은 쿼리를 두 번 수행할 때, 첫 번째 쿼리에서 없던 레코드가 두 번째 쿼리에서 나타나는 현상
- 한 트랜잭션이 수행중일 때 다른 트랜잭션이 새로운 레코드가 삽입함으로써 나타난다.
READ UNCOMMITTED
- 각 트랜잭션의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관없이 다른 트랜잭션에서 보인다.
- 사용자 A가 처리 도중 알 수 없는 문제가 발생해 INSERT된 내용(“Lara” 사원)을 ROLLBACK한다고 하더라도 여전히 사용자 B는 “Lara”가 정상적인 사원이라고 생각하고 계속 처리할 문제가 생길 수도 있다.
- DIRTY READ가 허용되는 격리 수준이며, RDBMS 표준에서는 트랜잭션 격리 수준으로 인정하지 않는다. 이 현상으로 인해 개발자와 사용자가 데이터에 대해 혼동이 생길 수 있다.
- MySQL에서는 최소한 READ COMMITTED 이상의 격리 수준을 사용할 것을 권장한다.
READ COMMITTED
- Oracle DBMS의 기본 격리 수준이며, 가장 많은 서비스에서 선택되는 격리 수준이다.
- 특정 트랜잭션에서 데이터를 변경했더라도 COMMIT이 완료된 데이터만 다른 트랜잭션에서 조회할 수 있다.
- NON-REPEATABLE READ 현상이 생길 수 있다.
- REPEATABLE READ는 한 트랜잭션 내에서 동일한 SELECT문의 결과가 같아야 한다는 의미이다.
- 하지만 다른 트랜잭션 내에서 데이터의 변경이나 삭제에 따라 SELECT문의 결과가 달라질 수 있다.
REPEATABLE READ
- MySQL의 InnoDB 스토리지 엔진에서 기본으로 사용되는 격리 수준이다.
- 트랜잭션이 ROLLBACK될 가능성에 대비해 변경되기 전 레코드를 Undo 공간에 백업해두고 실제 레코드 값을 변경한다.(MVCC)
- 트랜잭션이 시작된 이후에 emp_no가 500000인 “Lara”를 “Toto”로 변경하고 COMMIT했지만, 두 번째 SELECT에서 Undo에 백업된 데이터에 의해 “Lara”의 데이터가 조회된다.
- 한 트랜잭션 안에서의 SELECT문은 결과가 동일하다는 것을 볼 수 있다.
- PHANTOM READ 현상이 발생할 수 있다.
- 다른 트랜잭션에서 수행한 변경 작업에 대해 레코드가 보였다 안 보였다 하는 증상
- SELECT … FOR UPDATE는 SELECT하는 레코드에 Lock을 걸어야 하는데 Undo 공간에는 잠금을 걸 수 없기 때문에 SELECT… FOR UPDATE나 SELECT … LOCK IN MODE는 현재의 레코드의 값을 가져오기 때문에 바뀐 값을 가져올 수가 있다.
- MySQL에서는 갭 락과 넥스트 키 락 덕분에 REPEATABLE READ 격리 수준에서도 PHANTOM READ가 발생하지 않는다.
SERIALIZABLE
- 가장 단순한 격리 수준이면서 동시에 가장 엄격한 격리 수준이다.
- 동시 성능이 가장 좋지 않다.
- 읽고 쓰는 레코드에 대해 다른 트랜잭션에서는 절대 접근할 수 없다.
- PHANTOM READ가 발생하지 않는다.
MySQL에서 격리 수준 보는 방법
MySQL 8.4.2 버전에서 조회했다.
기본 격리 수준은 위에서 언급했듯이 ‘REPEATABLE-READ’이다.
1
SELECT @@GLOBAL(or SESSION).transaction_isolation
MySQL에서 격리 수준 바꾸는 방법
1
2
3
4
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
참고
This post is licensed under CC BY 4.0 by the author.