Search
Duplicate
4️⃣

MySQL의 격리 수준

트랜잭션의 격리 수준이란 여러 트랜잭션이 동시에 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터를 볼 수 있게 허용할 지, 말 것인지를 결정하는 것
격리 수준은 크게 READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZABLE 총 4개 DIRTY READ라고도 하는 READ UNCOMMITTED는 일반적인 데이터베이스에서는 거의 사용하지 않으며 SERIALIZABLE 또한 동시성이 중요한 데이터베이스에서는 거의 사용하지 않음
4개의 격리 수준 중 뒤로 갈수록 각 트랜잭션 간의 데이터 격리 정도가 높아짐
일반적으로 격리 수준이 높아질수록 처리 성능이 떨어질 것이라고 생각하는 사용자가 많은데 SERIALIZABLE 격리 수준이 아니면 크게 성능의 저하가 발생하지는 않는다.
데이터베이스 격리 수준을 이야기하면 세 가지 부정합의 문제점이 항상 논해지는데, 이 세가지 부정합 문제는 격리 수준의 레벨에 따라 발생할 수도 있고 않을수도 있다.
DIRTY READ
NON-REPEATABLE READ
PHANTOM READ
READ UNCOMMITTED
발생
발생
발생
READ COMMITTED
없음
발생
발생
REPEATABLE READ
없음
없음
발생(InnoDB는 없음)
SERIALIZABLE
없음
없음
없음
: 서비스 용도의 데이터베이스는 READ COMMITTEDREPEATABLE READ 중 하나를 사용, 오라클 같은 DBMS에선 READ COMMITTED를 주로 사용, MySQL에서는 REPEATABLE READ를 주로 사용

1. READ UNCOMMITTED

: READ UNCOMMITTED 격리 수준에서는 각 트랜잭션의 변경 내용이 COMMIT이나 ROLLBACK 여부에 상관없이 다른 트랜잭션에서 볼 수 있음
: 이처럼 처리한 작업이 완료되지 않았음에도 다른 트랜잭션에서 볼 수 있는 현상을 더티 리드(Dirty read)라고 하며 유일하게 더티 리드가 허용되는 수준

2. READ COMMITTED

: 오라클 DBMS에서 기본으로 사용되는 격리 수준으로 온라인 서비스에서 가장 많이 선택되는 격리 수준
: 더티 리드같은 현상은 발생하지 않으며 트랜잭션이 진행중인 데이터에 다른 트랜잭션이 접근하며 트랜잭션이 진행중인 레코드의 기존 값이 언두 영역에 백업되고 해당 값을 보여준다. 이는 트랜잭션이 끝난 시점에서의 조회와 진행중인 시점의 조회값이 달라지는데, 이는 REPEATABLE READ 정합성에 어긋나는 것
⇒ 하나의 트랜잭션에서 같은 작업을 수행했는데, 시점이 달라졌다고 결과가 달라진다라.. 마다라.. 데이다라..
: 트랜잭션의 중요한 점은 격리 수준에 따라 실행하는 SQL 문장이 어떤 결과를 불러올지를 정확히 예측할 수 있어야 한다는 것, 사용자 중 트랜잭션 내에서 실행되는 SELECT과 트랜잭션없이 실행되는 SELECTREADT COMMITTED 격리 수준에서는 별로 차이가 없다. 하지만 REPEATABLE READ 격리 수준에서는 기본적으로 SELECT 쿼리 문장도 트랜잭션 범위 내에서만 작동, 즉 START TRANSACTION 또는 BEGIN 명령으로 트랜잭션을 시작한 상태에서 온종일 동일한 쿼리를 반복해서 실행해봐도 동일한 결과만 보게됨

3. REPEATABLE READ

: InnoDB 스토리지 엔진에서 기본으로 사용되는 격리 수준으로 바이너리 로그를 가진 MySQL 서버에서는 최소 이 수준 이상을 사용해야 함
: 이 격리 수준에서는 NON-REPEATABLE READ 부정합이 발생하지 않는다.
: InnoDB 스토리지 엔진이 트랜잭션이 ROLLBACK 될 가능성에 대비해 변경되기 전 레코드를 언두 공간에 저장해두고 실제 레코드 값을 변경하는데 이를 MVCC라고 함.
: 사실 READ COMMITTEDMVCC를 이용해 COMMIT되기 전의 값을 보여주는데, 둘의 차이는 언두 영역에 백업된 레코드의 여러 버전 가운데 몇 번째 이전 버전까지 찾아 들어가야 하느냐에 있다.
: 모든 InnoDB의 트랜잭션은 고유한 트랜잭션 번호를 가지며 언두 영역에 백업된 모든 레코드에는 변경을 발생시킨 트랜잭션의 번호가 포함되어 있으며 언두 영역에 백업된 모든
레코드는 InnoDB 스토리지 엔진이 불필요 하다고 판단하는 시점에 주기적으로 삭제됨, REPEATABLE READ 격리 수준에서는 MVCC를 보장하기 위해 실행 중인 트랜잭션 가운데
가장 오래된 트랜잭션 번호보다 트랜잭션 번호가 앞선 언두 영역의 데이터는 삭제할 수가 없다. 그렇다고 가장 오래된 트랜잭션 번호 이전의 트랜잭션에 의해 변경된 데이터는
필요한 것은 아니다. 즉 특정 트랜잭션 번호의 구간 내에서 백업된 언두 데이터가 보존되어야 한다.
: 이 수준에서는 PAHNTOM READ 부정합이 발생하는데, 내가 특정 시점에서 조회한 데이터를 추후에 조회하는 과정에서 누군가 데이터를 삽입했을 경우, 조회 결과가 달라지는 것을
안 보였다 보이게 되므로 이처럼 보였다 안보였다하는 것을 PAHNTOM READ 또는 PAHNTOM ROW라고 한다.

4. SERIALIZABLE

: 가장 단순한 격리 수준이면서 동시에 가장 엄격한 격리 수준으로 그만큼 동시 처리 성능도 다른 트랜잭션 격리 수준보다 떨어진다.
: 이 경우 읽기 작업도 잠금으로 처리되며 다른 트랜잭션은 그러한 레코드를 접근할 수 없게 되는 것이다.하지만 InnoDB 스토리지 엔진에서는 갭 락과 넥스트 키 락 덕분에
REPEATABLE READ 격리 수준에서도 PHANTOM READ가 발생하지 않으므로 굳이 사용할 필요는 없는 수준이다.
트랜잭션 격리수준은 세션별로 수정할 수 있는데, Datagrip 툴에선 이를 GUI로 지원한다..! 방금 발견함 2023-06-12 10:46, 신기하다
서비스 영역에서 설정하는데, 아마 모든 세션에 적용되는 것 같다.