SQL 질의어인 SELECT, INSERT, UPDATE, DELETE문을 이용해 데이터베이스에 접근하는 것과 같지만 질의어는 한 문장이 아닐 수 있다.
원자성
일관성
독립성
영속성
활동(Active): 트랜잭션이 실행중인 상태
부분 완료(Partially Committed): 트랜잭션의 마지막 연산까지 실행했지만 Commit 연산이 실행되기 직전의 상태
완료(Committed): 트랜잭션이 성공적으로 종료되어 Commit 연산을 실행한 후의 상태
실패(Failed): 트랜잭션 실행에 오류가 발생하여 중단된 상태
철회(Aborted): 트랜잭션이 비정상적으로 종료되어 Rollback 연산을 수행한 상태
트랜잭션 격리수준이란 동시에 여러 트랜잭션이 처리될 때, 트랜잭션끼리 얼마나 서로 고립되어 있는지를 나타낸다. 각 단계에 따라 발생할 수 있는 부정합 문제가 다르다.
즉, 특정 트랜잭션이 다른 트랜잭션이 변경한 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것이다.
격리수준의 종류를 알아보기 전에 먼저 발생할 수 있는 부정합 문제에 대해 살펴보자.
더티 리드는 다른 트랜잭션에서 처리한 작업이 완료되지 않았음에도 불구하고 다른 트랜잭션에서 볼 수 있게 되는 현상을 말한다.
A의 트랜잭션이 아직 커밋이 되지 않았음에도 불구하고 B가 조회한 결과는 삽입된 Jubal이 반환된다.
여기서 문제는 만약 A의 작업 도중 문제가 발생해 트랜잭션이 롤백되어도 B는 JuBal이 정상적인 데이터라고 판단해 작업을 계속 처리하게 된다는 것이다.
더티 리드가 허용되는 격리 수준은 READ UNCOMMITTED이고 해당 격리 수준은 피할 것이 권장된다.
그렇다면 더티 리드를 해결할 방법은 없을까?
READ COMMITTED 격리 수준에서는 Undo 로그를 활용해 더티 리드 문제를 해결한다.
Undo 영역은 UPDATE문이나 DELETE문 등을 활용해 데이터를 변경했을 때 변경되기 이전의 데이터를 보관하는 곳이다. INSERT문의 경우 해당 데이터의 row id를 저장하고 이를 활용해 물리적 메모리에 바로 접근할 수 있도록 보장한다.
NON-REPEATABLE READ란 하나의 트랜잭션 내에서 동일한 SELECT 쿼리를 실행했을 때 항상 같은 결과를 보장해야 한다는 REPEATABLE READ 정합성에 어긋나는 것을 말한다.
READ COMMITTED 격리 수준을 사용한다면 REPEATABLE READ가 보장되지 않으므로 SELECT 쿼리를 통해 작업을 수행하는 로직에서 실행마다 다른 결과가 온다면 큰 문제가 발생할 수 있다.
NON-REPEATABLE READ 문제는 READ COMMITTED에서 더티 리드를 해결했듯이 Undo 영역을 통해 문제를 해결할 수 있는데 방식이 약간 다르다.
REPEATABLE READ 격리 수준에서는 Undo 영역에 백업된 레코드의 여러 버전 가운데 몇 번째 버전을 보여주냐에 차이가 있다.
즉, 언두 영역에 백업된 모든 데이터에는 변경이 발생한 트랜잭션의 번호가 포함되어 있는데, REPEATABLE READ 격리 수준에서는 실행중인 트랜잭션보다 작은 트랜잭션에서 변경한 데이터만 보게 하여 NON-REPEATABLE READ 문제를 해결한다.
PHANTOM READ란 SELECT … FOR UPDATE 쿼리와 같이 쓰기 잠금을 거는 경우 다른 트랜잭션에서 수행한 변경 작업에 의해 레코드가 보였다 안 보였다 하는 현상을 말한다.
NON-REPEATABLE READ 문제 해결에서 언급한 것처럼 동일한 트랜잭션 내에서의 동일한 쿼리는 항상 같은 결과를 출력해야 한다. 하지만 위 그림에서 SELECT … FOR UPDATE 쿼리의 경우 SELECT하는 레코드에 쓰기 잠금을 걸어야 하는데, 언두 영역에는 잠금을 걸 수 없기 때문에 어쩔 수 없이 SELECT ... FOR UPDATE 나 SELECT ... LOCK IN SHARE MODE 로 조회되는 레코드는 언두 영역의 변경 전 데이터를 가져오는 것이 아니라 현재 레코드의 값을 가져온다.
InnoDB 스토리지 엔진은 레코드 락과 갭 락을 합친 넥스트 키 락을 사용한다. t 테이블에 c1 = 13 , c = 17 인 두 레코드가 있다고 가정하자. 이때 SELECT c1 FROM t WHERE c1 BETWEEN 10 AND 20 FOR UPDATE 쿼리를 수행하면, 10 <= c1 <= 12, 14 <= c1 <= 16, 18 <= c1 <= 20 인 영역은 전부 갭 락에 의해 락이 걸려서 해당 영역에 레코드를 삽입할 수 없다. 또한 c = 13, c = 17인 영역도 레코드 락에 의해 해당 영역에 레코드를 삽입할 수 없다. 참고로 INSERT 외에 UPDATE, DELETE 쿼리도 마찬가지이다.
이러한 방식으로 InnoDB 스토리지 엔진은 넥스트 키 락을 이용하여 PHANTOM READ 문제를 해결한다.
Do you want to play games with your friends?. Two Player Games is one of the websites that will have many games for two players that are very interesting. There are games when playing two you will be teammates and there will be fighting games where two you will compete directly with each other.