구분 | 설명 |
---|---|
Dirty read | 커밋되지 않은, Dirty한 데이터 읽기가 허용됨. 데이터 무결성은 깨지고, 외부키 제약은 위배되고, 유일성 제약은 무시됨. |
Non-Repeatable read | 시간 T1에서 읽은 로우를 시간 T2에서 다시 읽고자 할 때 로우가 바뀌었거나, 사라졌거나 또는 수정되어 있는 현상. |
Phantom read | 시간 T1에서 쿼리를 실행하고 시간 T2에서 쿼리를 재 실행했는데, 그 사이 T1에 없던 로우가 데이터베이스에 추가되어 결과가 달라질 수 있음. 이미 읽은 데이터가 변경된 것이 아니라, 쿼리 조건을 만족하는 데이터가 전보다 많아졌음을 의미하는 것으로 'Non-Repeatable read'와 다름. |
고립수준 | Dirty Read | Non-Repeatable Read | Phantom Read |
---|---|---|---|
READ UNCOMMITTED | 허용 | 허용 | 허용 |
READ COMMITTED | -- | 허용 | 허용 |
REPEATABLE READ | -- | -- | 허용 |
SERIALIZABLE | -- | -- | -- |
<READ COMMITTED 고립을 사용하는 비오라클 데이터베이스 타임라인>
시간 | 쿼리 | Account 이체 트랜잭션 |
---|---|---|
T1 | 로우 1을 읽는다. account는 123, 값은 $500, 지금까지의 합계는 $500.00 이다. | -- |
T2 | 로우 2을 읽는다. account는 456, 값은 $240.25, 지금까지의 합계는 $740.25 이다. | -- |
T3 | -- | 로우 1을 수정하고 다른 수정이나 읽기를 막기 위해 배타 락을 건다. 로우 1은 $500.00에서 $100.00으로 수정되었다. |
T4 | 로우 N을 읽는다. 지금까지의 합계는... | |
T5 | -- | 로우 342,023(account 987)을 수정하고 배타 락을 건다. 로우 342,023은 $100에서 $500으로 수정되었다. |
T6 | 로우 342,023(account 987)을 읽으려고 하지만, 락이 걸려 있다는 것을 발견한다. 이 세션은 블로킹된 채로 이 로우를 포함하고 있는 블록을 사용할 수 있을 때까지 기다린다. (쿼리에 대한 처리는 중지된다) | -- |
T7 | -- | 트랜잭션을 커밋한다. |
T8 | 로우 342,023(account 987)을 읽고, $500.00을 더한다. 결국 $400.00을 두 번 더한 꼴이 된다. | -- |
<REPEATABLE READ 고립을 사용하는 비 오라클 데이터베이스 타임라인 #1>
시간 | 쿼리 | Account 이체 트랜잭션 |
---|---|---|
T1 | 로우 1을 읽는다. 합계는 $500.00, 블록 1은 로우 1에 공유 락을 갖고 있다. | -- |
T2 | 로우 2을 읽는다. 지금까지의 합계는 $740.25, 블록 2은 로우 2에 공유 락을 갖고 있다. | -- |
T3 | -- | 로우 1을 수정하려고 하지만, 블로킹한다. 트랜잭션은 배타 락을 획득할 때까지 중지된다. |
T4 | 로우 N을 읽는다. 합계는... | -- |
T5 | 로우 342,023을 읽는다. $100을 합계에 더한다. | -- |
T6 | 트랜잭션을 커밋한다. | -- |
T7 | -- | 로우 1을 수정하고 블록에 배타 락을 건다. 로우 1은 $100.00으로 수정되었다. |
T8 | -- | 로우 342,023을 수정하고 블록에 배타 락을 건다. 로우 342,023은 $500.00으로 수정되었다. 트랜잭션을 커밋한다. |
<REPEATABLE READ 고립을 사용하는 비 오라클 데이터베이스 타임라인 #2>
시간 | 쿼리 | Account 이체 트랜잭션 |
---|---|---|
T1 | 로우 1을 읽는다. 합계는 $500.00, 블록 1은 로우 1에 공유 락을 갖고 있다. | -- |
T2 | 로우 2을 읽는다. 지금까지의 합계는 $740.25, 블록 2은 로우 2에 공유 락을 갖고 있다. | -- |
T3 | -- | 로우 342,023을 수정하고 다른 수정과 공유 읽기를 막기 위해 블록 342,023에 배타 락을 건다. |
T4 | 로우 N을 읽는다. 합계는 ... | -- |
T5 | -- | 로우 1을 수정하려고 하지만 블로킹된다. 트랜잭션은 배타 락을 획득할 수 있을 때까지 중지된다. |
T6 | 로우 342,023을 읽으려고 하지만, 이미 배타 락이 걸려 있어서 읽을 수 없다. | -- |
--ERROR at line 1:
--ORA-08177: can't serialize access for this transaction
1. 누군가 같은 데이터를 변경할 가능성이 매우 낮을 때
2. 트랜잭션 수준의 읽기 일관성이 필요할 때
3. 트랜잭션 수행 시간이 짧을 때(위 첫 번째 항목을 실현하는 데 도움이 될 만큼)
<READ COMMITTED 모드>
-- 1. (Session_1) 샘플 데이터 생성
CREATE TABLE A (X INT);
CREATE TABLE B (X INT);
-- 2. (Session_1) 데이터 생성
INSERT INTO A
SELECT COUNT(*)
FROM B
;
COMMIT
;
SELECT *
FROM A
;
X
----------
0
1 row selected.
;
-- 3. (Session_2) 데이터 생성
INSERT INTO B
SELECT COUNT(*)
FROM A
;
COMMIT
;
SELECT *
FROM B
;
X
----------
1
1 row selected.
;
<SERIALIZABLE 모드>
-- 1. (Session_1) 샘플 데이터 생성
DROP TABLE A;
DROP TABLE B;
CREATE TABLE A (X INT);
CREATE TABLE B (X INT);
-- 2. (Session_1) 세션 변경
ALTER SESSION SET ISOLATION_LEVEL=SERIALIZABLE;
-- 3. (Session_1) 데이터 생성
INSERT INTO A
SELECT COUNT(*)
FROM B
;
COMMIT
;
SELECT *
FROM A
;
X
----------
0
1 row selected.
;
-- 4. (Session_2) 세션 변경
ALTER SESSION SET ISOLATION_LEVEL=SERIALIZABLE;
-- 5. (Session_2) 데이터 생성
INSERT INTO B
SELECT COUNT(*)
FROM A
;
COMMIT
;
SELECT *
FROM B
;
X
----------
1
1 row selected.
;