트랜잭션 격리수준(isolation level)이란 동시에 여러 트랜잭션이 처리될 때, 트랜잭션끼리 얼마나 서로 고립되어 있는지를 나타내는 것이다.
즉, 간단하게 말해 특정 트랜잭션이 다른 트랜잭션에 변경한 데이터를 볼 수 있도록 허용할지 말지를 결정하는 것이다.
데이터베이스 트랜잭션이 안전하게 수행된다는 것을 보장하기 위한 성질 네가지가 존재합니다. (ACID)
원자성(Atomicity): 한 트랜잭션 내에서 실행한 작업들은 하나로 간주함 (모두 성공 또는 모두 실패)
일관성(Consistency): 트랜잭션은 일관성 있는 데이터베이스 상태를 유지해야 함
격리성(Isolation): 동시에 실행되는 트랜잭션들이 서로 영향을 미치지 않아야 함
지속성(Durability): 트랜잭션을 성공적으로 마치면 결과가 항상 저장되어야 함
격리수준은 크게 아래의 4개로 나뉜다.
1. READ UNCOMMITTED
2. READ COMMITTED
3. REPEATABLE READ
4. SERIALIZABLE
각 각의 특징에 대해서 정리하고 DB마다 격리수준이 다르기 때문에 DB선택시 성능적인 부분과 데이터 안정성에 부분을 고려해야한다.
A 트랜잭션이 시작하고 처음 조회한 데이터의 스냅샷을 저장하고 이후에 동일한 쿼리를 호출하면 스냅샷에서 데이터를 가져옵니다. 중간에 B 트랜잭션이 새로 커밋해도 A 트랜잭션이 조회하는 데이터는 변하지 않습니다.
원래는 다른 트랜잭션에서 commit이 일어나면 해당 undo log는 삭제하게 되는데, REPEATABLE READ에서는 이 구조를 유지하기 위하여, 요청한 트랜잭션 이전의 트랜잭션에 의해 생성된 언두 영역은 삭제 대상에 포함시키지 않고, 해당 데이터들만 볼 수 있도록 설계되어 있음
두개의 차이점은 하나의 트랜잭션에서 데이터 값이 변경하느냐 안하느냐의 차이다
Read Committed의 경우
-> 하나의 트랜잭션에서 동일한 조회 과정 수행이 되는동안 다른 트랜잭션에서 커밋이 일어나면 동일한 조회의 결과값이 달라질 수 있다. ( 매 조회마다 새로운 SNAPSHOT을 생성)
Reaeatable read의 경우
-> 하나의 트랜잭션이 시작하기전에 첫 조회시 만들어진 SNAPSHOT을 기반으로 조회 결과를 반환한다. 그래서 다른 트랜잭션에서 작업이 일어나도 하나의 트랜잭션의 범위 안에서는 동일한 내용을 출력한다.
Mysql의 innoDB를 통해 Phantom Read를 방지하지만 Update 쿼리시 특이한 경우로 발생할 수 있다
Phantom Read
A : START TRANSACTION;
A : SELECT * FROM test; # 최초 Snapshot 생성
B : INSERT INTO test (id, name, age) VALUES (5, 'test', 26); # Lock 이 걸려있지 않기 때문에 Gap 에 데이터 삽입 가능
A : SELECT * FROM test; # 최초 Snapshot 을 그대로 사용
A : UPDATE test SET name = 'twenty-six' WHERE age = 26; # Locking Read 를 통해 새롭게 읽은 후 UPDATE
A : SELECT * FROM test; # Snapshot 이 초기화되어 Phantom Read 발생
트랜잭션을 읽기 전용으로 변경합니다.
만약 읽기 전용 트랜잭션 내에서 INSERT, UPDATE, DELETE 작업을 해도 반영이 되지 않거나 DB 종류에 따라서 아예 예외가 발생하는 경우도 있습니다.
성능 향상을 위해 사용하거나 읽기 외의 다른 동작을 방지하기 위해 사용하기도 합니다.
왜 성능이 향상될까? -> JPA 에는 Dirty Checking 이라는 기능이 있음
개발자가 임의로 UPDATE 쿼리를 사용하지 않아도 트랜잭션 커밋 시에 1차 캐시에 저장되어 있는 Entity 와 스냅샷을 비교해서 변경된 부분이 있으면 UPDATE 쿼리를 날려주는 기능
readOnly = true 옵션을 주면 스프링 프레임워크가 하이버네이트의 FlushMode 를 MANUAL 로 설정해서 Dirty Checking 에 필요한 스냅샷 비교 등을 생략하기 때문에 성능이 향상
작성중