MySQL InnoDB의 기본 트랜잭션 격리 수준은?
테마
테마
격리 수준(isolation level)은 동시에 실행되는 트랜잭션(transaction)이 서로의 변경을 어디까지 볼 수 있는가를 정하는 규칙이다. 격리를 강하게 할수록 이상 현상(anomaly)은 줄고 동시성은 떨어진다.
트랜잭션을 완전히 한 줄로 세워 하나씩 실행하면 안전하지만 느리다. 반대로 아무 제약 없이 섞어 돌리면 변경을 확정하는 커밋(commit)을 아직 하지 않은 값을 읽거나, 같은 행을 두 번 읽었는데 값이 달라지는 일이 생긴다. 격리 수준은 이 둘 사이에서 어떤 이상 현상까지 허용할지를 고르는 다이얼이다. SQL 표준(SQL-92)이 4단계를 정의하고, 엔진마다 실제 동작은 조금씩 다르다.
표준이 구분하는 이상 현상은 더티 리드(dirty read), 반복 불가능한 읽기(non-repeatable read), 팬텀 리드(phantom read) 세 가지다. 각각의 뜻은 표 아래에서 설명한다. 표의 "발생"은 그 격리 수준에서 해당 현상이 생길 수 있다는 뜻이다.
| 격리 수준 | 더티 리드 | 반복 불가능한 읽기 | 팬텀 리드 |
|---|---|---|---|
| READ UNCOMMITTED | 발생 | 발생 | 발생 |
| READ COMMITTED | 방지 | 발생 | 발생 |
| REPEATABLE READ (InnoDB 기본) | 방지 | 방지 | 표준은 허용, InnoDB는 대부분 방지* |
| SERIALIZABLE | 방지 | 방지 | 방지 |
* InnoDB의 일반 SELECT는 트랜잭션 내내 같은 읽기 뷰(read view)를 유지하므로 팬텀이 보이지 않는다. 잠금 읽기(locking read)와 UPDATE·DELETE는 넥스트키 락(next-key lock)으로 스캔한 범위에 새 행이 삽입되는 것을 막는다. 다만 잠금 없이 스냅샷(snapshot)을 읽는 일관된 읽기(consistent read)와 잠금 읽기를 한 트랜잭션에서 섞으면 서로 다른 시점의 행이 보일 수 있다. 그래서 "무조건 없다"고 단정하면 안 된다.
세 이상 현상은 이렇게 구분한다.
REPEATABLE READ였다면 T1은 첫 SELECT 시점의 스냅샷을 계속 보므로 두 번째도 100이 나온다.
기억법
격리 수준 4개는 "이상 현상 3개를 위에서부터 하나씩 끈다"로 외운다. READ COMMITTED가 더티 리드를, REPEATABLE READ가 반복 불가능한 읽기를, SERIALIZABLE이 팬텀 리드를 끈다.
이어지는 내용은 트랜잭션 격리수준 2에서 다룬다. InnoDB가 스냅샷과 잠금으로 각 수준을 어떻게 구현하는지, 다른 엔진과 무엇이 다른지, 실무에서 무엇을 조심하는지를 본다.
MySQL InnoDB의 기본 트랜잭션 격리 수준은?
InnoDB REPEATABLE READ에서 팬텀 리드를 막는 데 쓰이는 잠금은?
현재 세션의 격리 수준을 조회하는 MySQL 8 구문
SELECT @@.transaction_isolation;