본문 바로가기
DB/SQL튜닝

SQL 튜닝이론) 트랜잭션 (트랜잭션 네가지 조건, 트랜잭션 격리성 수준, READ UNCOMMITTED, READ COMMITTED, REPEATABLE READ, SERIALIZEABLE READ

by 참외롭다 2024. 4. 19.
반응형

 

트랜잭션은 업무처리를 위한 논리적인 작업단위 입니다. 하나 이상의 갱신연산을 포함합니다. 데이터를 일관성있게 처리하려면 트랜잭션에 속한 두 개 이상의 연산을 동시에 처리할 수 있어야하는데 이는 불가능합니다. DBMS는 차선책으로 여러 개의 갱신연산이 하나의 작업처럼 전부 처리되거나 아예 처리되지않도록 하나의 단위로 처리합니다.

트랜잭션의 네가지 특징

정확한 트랜잭션은 다음과 같은 요건을 만족해야합니다.

원자성

트랜잭션은 분해가 불가능한 최소업무단위입니다. 내부의 거래가 전부 처리되거나 아예처리되지 않아야합니다.

일관성

트랜잭션 실행 후 데이터베이스 전체의 상태가 실행 전과 마찬가지로 일관되야합니다.

격리성

실행 중인 트랜잭션의 대상 레코드에 다른 트랜잭션이 접근할 수 없습니다.

영속성

트랜잭션이 실행을 성공적으로 완료하면 그 결과는 데이터베이스에 영속적으로 저장됩니다.

 

트랜잭션 격리성

 

격리성은 일관성과 마찬가지로 강한 LOCK을 오래 유지할수록 높아집니다.

 

낮은 단계의 격리성 수준에서 발생할 수 있는 현상

 

DIRTY READ

 

다른 트랜잭션이 수정할 후 커밋하지 않은 데이터를 읽는 것을 말합니다. 커밋되지 않은 값을 읽었는데 그 값이 롤백된다면 값을 읽은 트랜잭션은 비일관 상태에 놓이게 됩니다.

NON-REPEATABLE READ

 

트랜잭션 내에서 동일한 쿼리를 두 번 수행하는데 그 사이에 다른 트랜잭션이 같은 대상 레코드를 수정/삭제해서 동일 쿼리의 수행결과가 달라지는 경우입니다.

 

PANTOM READ

 

트랜잭션 내에서 동일한 쿼리를 두 번 수행하는데 다른 트랜재션으로 인해 첫 번째 쿼리에서 없던 레코드가 두번째 쿼리에서 나타나는 현상을 말합니다.

 

트랜잭션 격리성 수준

 

READ UNCOMMITTED

 

트랜잭션에서 처리중인 아직 커밋되지 않은 데이터를 다른 트랜잭션이 읽는 것을 허용합니다.

 

READ COMMITTED

 

커밋되어 확정된 데이터만 다른 트랜잭션이 읽도록 허용합니다. 이를 통해 DIRTY READ 현상을 방지합니다. 이 수준에서는 NONE-REAPEATABLE READ와 PHANTOM READ 현상을 막지못합니다. 동일한 쿼리라도 실행시점에 따라 결과가 달라질 수 있습니다.

 

REPEATABLE READ

 

트랜잭션 내에서 쿼리를 두 번 이상 수행할 때, 첫 번째 쿼리에 있던 레코드가 사라지거나 값이 바뀌는 현상을 방지합니다. 이 격리성 수준에서 PHANTOM READ 현상을 막지는 못합니다. 첫 번째 쿼리에 없던 새로운 레코드가 나타날 수 있습니다.

 

SERIALIZEABLE READ

 

트랜잭션 내에서 쿼리를 두 번 이상 수행할 때, 첫 번째 쿼리에 잇던 레코드가 사라지거나 값이 바뀌지 않고 새로운 레코드가 나타지도 않습니다. ORACLE의 경우 READ COMMITED와 SERIALIZABLE READ만 지원합니다. 트랜잭션 격리성 수준을 SERIALIZABLE READ로 상향조정하는 예시입니다.

 

set transaction isolation level read serializable;

 

TX1 트랜잭션을 REPEATABLE READ 모드에서 실행하면 T1 시점에 1번 쿼리에서 설정한 공유 LOCK을 T6까지 유지하므로 TX2의 UPDATE는 T6 시점까지 대기합니다.

 


-- TX1                  |             TX2
-- SELECT 잔고           t1
-- INTO BALANGE         |
-- FROM  계좌            |
-- WHERE 계좌번호 = 123;  |
--                      t2    UPDATE 계좌
--                      |      SET 잔고 = 잔고 - 5000
--                      |      WHERE 계좌번호 = 123;
--                      |
--                      t3    COMMIT;
--                      |
-- UPDATE 계좌           t4
-- SET 잔고 = 잔고 - 10000 |
-- WHERE 계좌번호 = 123    |
-- AND 잔고 >= 100000;    |
--                      |
-- IF SQL %ROWCOUNT = 0 t5
-- THEN                 |
-- ALERT('잔고부족');      |
-- END IF;              |
--                      |
-- COMMIT;              t6

 

이런 방식의 거래는 동시성에 문제가 있습니다. 대량의 데이터를 읽어 처리할 때는 동시성이 크게 낮아집니다. 동시성을 높이기 위해 'SNAPSHOT 격리성 수준' 이라고 불리는 방식을 사용합니다. 현재 진행 중인 트랜잭션에 의해 변경된 데이터를 일고자 할때는 변경 이전 상태의 SNAPSHOT을 이용합니다. 변경이 확정되지 않은 값을 읽는 것이 아니므로 LOCK을 설정할 필요가 없습니다.

 

반응형