목차
- 트랜잭션 고립 수준
- 종류
- 참고
트랜잭션 고립 수준
동일한 트랜잭션 시나리오 (입력, 작업)에도 불구하고 고립 수준에 따라 그 결과가 다를 수 있습니다. ANSI / ISO SQL 표준에서는 이와 같은 트랜잭션 고립 수준을 4가지로 분류하여 정의하고 각 고립 수준에서는 아래 3가지 현상을 허용할지 말지에 대해 정의합니다.
- dirty read (Uncommitted Dependency)
- Non-Repeatable Read (Inconsistent Analysis)
- Phantom Read
dirty read (Uncommitted Dependency)
커밋되지 않은 데이터 (dirty data)를 읽는 것을 말합니다. 이 때문에 데이터 무결성이 깨지고, 외래 키 제약조건이 무시되는 등 여러 문제가 발생할 수 있습니다.
Non-Repeatable Read (Inconsistent Analysis)
기존에 읽은 로우를 다시 읽고자 할 때 해당 로우가 없어졌거나, 변경된 경우를 말합니다. 즉 한 트랜잭션에서 같은 로우를 두 번 이상 읽었는데 각 결과가 다를 수 있다는 것을 뜻합니다. 반대로 트랜잭션 내에서 같은 로우에 대해 항상 같은 값이 유지되는 것을 REPEATABLE READ 정합성이라고 합니다.
Phantom Read
트랜잭션 내부에서 같은 쿼리를 두 번 실행할 때 첫 번째 실행 시에 없던(phantom) 레코드 가 조회되는 현상입니다. 이는 다른 트랜잭션의 INSERT에 의해 발생하는 문제로, 쓰기 잠금 (wirte lock) 설정을 통해 방지할 수 있습니다. 같은 쿼리에 대하여 만족하는 데이터가 더 많아진다는 점에서 non-repeatable read와 다릅니다.
종류
고립 수준 (transcation level) | dirty read | non-repeatable read | phantom read |
READ UNCOMMITTED (0) | 허용 | 허용 | 허용 |
READ COMMITTED (1) | - | 허용 | 허용 |
REPEATABLE READ (2) | - | - | 허용 |
SERIALIZABLE (3) | - | - | - |
READ UNCOMMITTED (트렌젝션 레벨 0)
- COMMIT 하지 않은 내용도 다른 트랜잭션에서 확인 가능
- dirty read
- Non-Repeatable Read
- Phantom Read
- 데이터 정합성에 문제가 발생할 수 있어, RDBMS에서 표준 격리 수준으로 인정하지 않음
오라클은 dirty read를 허용하지 않습니다. 따라서 READ UNCOMMITED는 오라클에서 허용하지 않습니다. 그러나 오라클은 non-blocking read를 제공합니다. commit 되지 않은 로우를 읽을 수는 있다는 것입니다. 만일 사용자가 commit 되지 않은 로우 (locked row)를 읽으려 한다면 해당 데이터를 우회하여 언두 세그먼트(commit 되기 이전 데이터)를 읽어 들입니다. 그러므로 트랜잭션이 commit 되기를 기다리지 않고도 SELECT 할 수 있는 것입니다.
dirty read를 허용하는 데이터베이스의 경우 commit 되지 않은 updated 로우 (UPDATE 된 값)를 읽어 들입니다. 이는 내가 최초에 select 할 때와 값이 달라지면서 값을 가지고 이어서 여러 작업을 진행하면 UPDATE 한 사용자의 의도와 달리 여러 문제를 야기하게 됩니다.
...
요점은, dirty 읽기가 백해무익한 기능이라는 것이다. 적어도 오라클은 dirty 읽기가 불필요하며, 부정확한 결과를 내는일 없이 dirty 읽기의 장점 (no blocking)만 취했다.
...
출처 : "전문가를 위한 오라클 데이터베이스 아키텍처" chapter 07 동시성과 멀티 버저닝
READ COMMITTED (트렌젝션 레벨 1)
- COMMIT 된 내용만 다른 트랜잭션에서 확인 가능
- 오라클 RDBMS 기본 설정, 온라인 서비스에서 보편적으로 선택되는 레벨
- Non-Repeatable Read, Phantom Read
오라클의 경우 위에서 설명한 non-blocking 읽기를 제공하기 때문에 commit 되기까지 기다릴 필요가 없습니다. 이 레벨에서도 마찬가지입니다.
그러나 비오라클의 경우 COMMIT 될 때까지 기다려야 합니다. 쿼리를 실행시켰으나, 이미 다른 편집자가 해당 ROW를 편집 중이라면 COMMIT 할 때까지 기다리고 있는 비효율이 발생하게 됩니다. 즉 UPDATE와 READ가 충돌한 것입니다. 이 때문에 문장단위로 COMMIT을 하는 개발자들이 생기곤 합니다. 그러나 트랜잭션 처리란 하나의 작업 단위가 하나의 일관성에서 다음의 일관성으로 한 번에 그 상태를 바꾸는 작업 단위가 되어야 하는데 (= 여러 작업을 한 뒤 작업 마지막에 COMMIT or ROLLBACK), 이와 반대되는 습관이라고 볼 수 있습니다. 이는 오라클 사용자들이 꼽는 오라클의 장점이기도 합니다.
REPEATABLE READ (트렌젝션 레벨 2)
- 트랜잭션 내에서는 같은 로우에 대해서 항상 같은 값만 조회됨
- 즉 트랜잭션 시작 전에 COMMIT 된 내용들만 조회 가능 (=자기보다 낮은 트랜잭션 번호에서 COMMIT 된 내용)
- MYSQL RDBMS 기본 설정
비오라클의 경우 공유 읽기 LOCK을 채택함으로서 REAPEATABLE READ를 구현합니다. 이는 데이터를 읽는 자가 쓰는 자를 블로킹하는 것을 말합니다. 트랜잭션이 해당 로우를 읽기만 해도 lock을 풀지 않고 유지(스치기만 해도)하기 때문에 lost update를 방지할 수 있습니다. 그러나 이는 동시성을 저하하고, 교착상태에 빠질 수 있습니다.
오라클은 멀티 버저닝을 이용하여 쿼리가 실행되기 시작한 시점을 기준으로 일관성 있는 결과를 보여주고, 읽는 자와 쓰는 자가 서로 블로킹하지 않도록 합니다.
lost update (갱신 손실)
같은 로우에 대하여 A 사용자와 B 사용자가 있을 때 아래와 같이 실행했다.
t1. A가 트랜잭션 open & SELECT ROW
t2. B가 트랜잭션 open & SELECT ROW
t3. A 가 UPDATE ROW
t4. B가 UPDATE ROW
t5. A가 commit;
t6. B가 commit;
결과로 A의 UPDATE 가 덮어 씌어졌다 (= A update 미반영). 이런 현상을 lost update라 한다.
SERIALIZABLE (트렌젝션 레벨 3)
- 가장 단순하고 엄격한 격리 수준
- 작업 중인 레코드에 대해서 다른 트랜잭션에서 SELECT 불가능
- 동시처리 능력이 떨어짐. (성능 저하)
참고
전문가를 위한 오라클 데이터베이스 아키텍처 (저 : 토마스 카이트)
http://www.yes24.com/Product/Goods/5239961
'Programming > Database System' 카테고리의 다른 글
DISTINCT, GROUP BY 무엇을 쓸까 (1) | 2022.09.26 |
---|---|
[DBMS] 트랜잭션 (transaction) (0) | 2022.08.19 |
정규화 (0) | 2022.05.02 |
SQL (2) - 데이터 검색, SELECT (0) | 2022.04.04 |
SQL (1) - 데이터베이스 객체와 DDL, DML (0) | 2022.03.23 |
댓글