[MySQL] 트랜잭션 격리수준(Isolation level)
트랜잭션 : 하나의 작업처리단위
이렇게 작업을 하나씩 순차적으로 진행하면?
1)데이터무결성 보장(ACID특징)
모두 성공적으로 처리되나(Commit) 실패할 경우 원상태로 되돌아가기 때문에(Rollback) 부분업데이트가 발생하지 않음
*데이터 정합성(Automicity) 보장 : 트랜잭션 -> 동시에 수행되는 트랜잭션끼리 데이터의 일관성 유지하도록 보장
*데이터 고립성(Isolation) 제어 : Lock기능 -> 동시에 수행되는 트랜잭션끼리 영향을 미치지 않도록 제어
2)직렬화(Serialization)가 됨
하지만, 다수의 클라이언트가 DB에 동시에 접근해서 사용해야 됨 -> 동시성도 보장되어야 함 -> 어떻게?
격리수준(Isolation level)
동시에 여러 트랜잭션이 처리될 때
다른 트랜잭션이 변경하거나 조회하는 데이터를 허용할지 말지를 결정하는것
즉, 동시에 수행되는 트랜잭션끼리 어느정도 영향을 줄지 그 수준을 정하는 것
격리수준을 낮추면?
트랜잭션끼리 쿨하게 변경된 내용에 대해서 신경쓰지 않음.
그래서 서로 영향이 적어서 동시에 수행되도 상관없음(동시성 높아짐)
하지만, 신경안쓰고 영향을 안준다고 생각해서 지들끼리 변경하니까 데이터 무결성 보장이 어려움
격리수준을 높이면?
트랜잭션끼리 쪼잔하게 작은 변화에도 크게 영향을 미침
그래서 동시에 수행되서 변경되는 내용에 서로 영향이 있음(동시에 일어나기 어려움 = 동시성 낮아짐)
하지만, 서로 작은 변경에도 영향이 있으니까 데이터 다 일치시켜서 데이터 무결성 보장
LV0. READ UNCOMMITTED
COMIIT이나 ROLLBACK에 상관없이 트랜잭션에서 변경내용이 다른 트랜잭션에서 보여짐
그럼 문제없어? 더티리드 발생
*Dirty Read(더티리드) : 하나의 트랜잭션에서 작업이 완료 되지 않았는데도 다른 트랜잭션에서 볼 수 있게 되는 현상
직접 TEST해보기) 6번세션 : REPETABLE-READ 7번세션 : READ UNCOMMITTED
STEP1. 6번세션에서 A테이블에 INSERT 트랜잭션 수행 중 (아직 COMMIT까지 한게 아님)
STEP2. 7번세션에서 A테이블 SELECT 트랜잭션 수행 중 : 빈테이블이 아님!
->COMMIT된것도 아닌데 6번세션의 내용이 INSERT됨
STEP3. 6번세션에서 A테이블에 ROLLBACK 완료 : INSERT 사라짐
STEP4. 7번세선에서 A테이블 SELECT 트랜잭션 : 빈테이블
->ROLLBACK된거인데 6번 세션에서 INSET된 내용이 사라짐
LV1. READ COMMITTED (오라클 디폴트값)
COMIIT이 완료된 데이터만 다른 트랜잭션에서 보여짐
완료전에 다른트랜잭션에서 조회하면 언두영역에 백업된 레코드에서 값을 가져온다.
더티리드는 발생하지 않음
그럼 문제없어? NON-REPEATABLE READ 부정합(데이터 비일관성) 발생
*NON-REPEATABLE READ : 하나의 트랜잭션에서 같은 쿼리를 두번 이상 수행할때,
똑같은 쿼리임에도 다른 결과를 볼 수 있게 되는 현상
하나의 트랜잭션에서 같은 쿼리를 실행하면 같은 결과를 가져와야한다는 정합성에 어긋난다.
직접 TEST해보기) 6번세션 : REPETABLE-READ 7번세션 : READ COMMITTED
STEP1. 7번세션에서 A테이블에 SELECT 트랜잭션을 수행 중 : 빈테이블 (아직 COMMIT까지 한게 아님)
STEP2. 6번세션에서 A테이블에 INSERT 트랜잭션을 수행 -> COMMIT 완료 : 빈테이블이 아님! (INSET끝남)
SETP3. 7번세션에서 다시 A테이블에 SELECT 트랜잭션을 수행 : 빈테이블이 아님! (6세션의 내용이 INSET된다!)
-> 7번세션의 관점으로만 보면
A테이블에 같은 SELECT쿼리를 수행한건데 다른 결과를 갖게 되서 NON-REPEATABLE READ 발생
LV2. REPEATABLE RAED (MYSQL의 InnoDB엔진의 디폴트값)
COMIIT이 완료된 데이터만 다른 트랜잭션에서 보여짐
완료전에 다른트랜잭션에서 조회하면 언두영역에 백업된 레코드에서 값을 가져온다. // READ COMMITTED랑 같음
하지만, READ COMMITTED와의 차이점은 언두영역에 백업된 레코드 중 어떤 버전에서 가지고 오는지가 다르다.
그때, 백업된 버전들을 스냅샷로 찍어두고, 어떤 스냅샷을 가지고 오는지에 따라 값이 달라짐
더티리드는 발생하지 않음
NON-REPEATABLE READ 부정합(데이터 비일관성) 발생하지 않음
그럼 문제없어? Phantom READ 부정합 발생!! (하지만 InnoDB는 넥스트 키락때문에 발생하지 않음)
*Phantom READ : 하나의 트랜잭션에서 일정 범위의 레코드를 두번이상 읽을때,
똑같은 쿼리임에도 첫번째 쿼리에서 없던 레코드가 두번째 쿼리에서 나타나는 현상
트랜잭션 도중에 새로운 레코드가 삽입되면 안된다는 정합성에 어긋난다.
직접 TEST해보기)6번세션 : REPETABLE-READ 7번세션 : REPEATABLE RAED
STEP1. 7번세션에서 A테이블에 SELECT 트랜잭션을 수행 중 : 빈테이블 (아직 COMMIT까지 한게 아님)
STEP2. 6번세션에서 A테이블에 INSERT 트랜잭션을 수행 -> COMMIT 완료 : 빈테이블이 아님! (INSET끝남)
SETP3. 7번세션에서 다시 A테이블에 SELECT 트랜잭션을 수행 : 빈테이블! (6세션의 내용이 INSET되지 않는다!)
-> 왜? READ COMMITTED랑 다른점은? 7번세션의 관점으로만 보면
A테이블에 같은 SELECT쿼리를 수행할때, 같은 결과(빈테이블)를 갖게 되서 NON-REPEATABLE READ 발생하지 않음!
-> 왜 같은 결과를 갖게 되는가?
A테이블을 두번이상 읽는 상황이라 트랜잭션 번호를 부여받는데
SETP1에서 부여받은 트랜잭션번호 < STEP2에서 부여받은 트랜잭션 번호
그래서 SETP1에서 할당받은 트랜잭션(7번세션)에서는
그 이후의 트랜잭션 번호를 부여받은 INSET정보(6번세션)가 보이지 않는다.
LV3. Serializable RAED
트랜잭션에서 읽고 쓰는 레코드는 다른 트랜잭션에서 절대 접근할 수 없음
더티리드는 발생하지 않음
NON-REPEATABLE READ 부정합(데이터 비일관성) 발생하지 않음
Phantom READ 부정합 발생하지 않음
그럼문제없어? 대신 동시성이 낮아짐
읽기작업을 할때 조차도 lock을 걸기 때문에 동시에 접근할 수 없어짐
참고
https://idea-sketch.tistory.com/45?category=547413
http://egloos.zum.com/ljlave/v/1530887
https://notemusic.tistory.com/49