트랜잭션 격리 수준 (isolation Level)
트랜잭션 격리 수준 (isolation Level)
동시에 여러 트랜잭션이 실행된 경우 어떻게 동작할지를 명시
-
- Dirty Read (비커밋 읽기)
-
트랜잭션에서 커밋되기 전 작업 내용을 다른 트랜잭션에서 볼 수 있음
EX) A 라는 트랜잭션에서 id : 22, name: 이름을 insert 하고 커밋하지 않은 상태에서 B 라는 트랜잭션이 id: 22 를 select 하는 경우 읽을 수 있음. 이때 A 트랜잭션에서 커밋되지 않고 롤백되는 경우 데이터 정합성에 문제가 생김
👉 가능한 이유👈
InnoDB 엔진이 transaction 을 커밋하는 방식 때문에 가능. InnonDB 는 일단 commit 이 되지 않더라도 실행한 모든 쿼리를 DB 에 적용. 즉, 특별히 log를 보고 특정 시점의 snapshot을 복구하는 consistent read를 하지 않고 그냥 해당 시점의 DB 를 읽으면 dirty read
- 🌟 consistent read(일관적 읽기)
-
select 시 현재 DB 값이 아닌 특정 시점의 DB snapshot 을 읽어 오는 것
-
이 snapshot 은 commit 된 변화만이 저장된 것을 의미
-
InnoDB 엔진은 각 쿼리를 실행할 때마다 실행한 쿼리의 log를 차곡차곡 저장한다. 그리고 나중에 consistent read를 할 때 이 log를 통해 특정 시점의 DB snapshot을 복구하여 가져온다.
-
- Non-Repeatable Read (비반복 읽기)
-
한 트랜잭션에서 같은 쿼리를 두번 실행시 그 사이 다른 트랜잭션이 값을 수정, 삭제 해서 두 쿼리의 결과가 상이하게 나타남
-
- Phantom Read (가상 읽기)
-
한 트랜잭션 안에서 일정 범위의 레코드를 두번 이상 읽을 때, 첫번째 쿼리에서 없던 레코드가 두번째 쿼리에서 나타나는 현상
격리 수준은 해당 문제가 발생하는지에 따라 분류
분리 레벨 | Dirty Read | Non-Repeatable Read | Phantom Read |
---|---|---|---|
READ UNCOMMITEED | 발생 | 발생 | 발생 |
READ COMMITTED | - | 발생 | 발생 |
REPEATABLE READ | - | - | 발생 |
SERIALIZABLE | - | - | - |
- READ UNCOMMITTED
- SELECT 쿼리를 실행 할 때 다른 트랜잭션에서 커밋되지 않은 데이터를 읽을 수 있음
- Dirty Read, Non-Repeatable Read, Phantom Read 발생
- 오라클은 이 레벨 지원 X
- READ COMMITTED
- 커밋 완료된 데이터만 읽을 수 있는 격리수준
- Non-Repeatable Read, Phantom Read 발생
- DB2, SQL Server, Sybase의 경우 Shared Lock을 이용해서 구현, 하나의 레코드를 읽을 때 Lock을 설정하고 해당 레코드에서 빠지는 순간 Lock해제 => Select 문으로 읽을 때만 해당 Row 에 대해 S Lock 이 걸림
- Oracle은 Lock을 사용하지 않고 쿼리시작 시점의 Undo 데이터를 제공하는 방식으로 구현
- 매번 read 마다 consistent read(일관적 읽기)를 통한 새로운 snapshot 을 생성 ➡️ Non-Repeatable Read, Phantom Read 발생
- Record lock 만 사용하고 Gap lock 사용 X
- REPEATABLE READ
- 하나의 트랜잭션에서 반복되는 SELECT 는 항상 같은 값을 조회
- 처음 read 한 시간을 기록하고 그 이후 모든 select 마다 처음 시점을 기준으로 consistent read 수행 ➡️ Non-Repeatable Read 발생 X
- 트랜잭션이 완료 될 때까지 해당 데이터에 대한 갱신, 삭제가 불가능 (해당 row 에 Shared Lock 이 걸림)
- InnoDB 엔진에서 사용하는 기본 격리 수준
- DB2, SQL Server의 경우 트랜잭션 고립화 수준을 Repeatable Read로 변경하면 읽은 데이터에 걸린 공유 Lock을 커밋할 때까지 유지하는 방식으로 구현 => 트랜잭션이 커밋 될 때까지 Select 문으로 읽은 Row 에 S Lock 이 걸림
- Oracle은 이 레벨을 명시적으로 지원하지 않지만 for update절을 이용해 구현 가능,
- SERIALIZABLE
- 트랜잭션이 완료 될 때까지 그 영역에 해당하는 데이터 수정(UPDATE) 및 입력(INSERT) 불가능
- 기본적으로 REPEATABLE READ 와 동일하지만
SELECT
쿼리가 전부SELECT ... FOR SHARE
로 자동 변경 -> 모든 select row 에 대해 S Lock 이 걸리고 X Lock (update, delete 등 불가능)
-> S Lock 걸린 row 에 update, delete 시도 시 deadlock - 동시성이 가장 떨어지고 쉽게 Dead Lock 에 걸릴 수 있음
- 많이 사용하지 않음
레퍼런스
트랜잭션, 트랜잭션 격리수준(Isolation Level)