트랜잭션과 락, 2차 캐시
jpa프로그래밍 16장 및 영속성 컨텍스트 설명 내용 정리
영속성 컨텍스트(1차 캐시)와 transaction
jpa는 트랜잭션을 commit하는 순간 영속성 컨텍스트에 있는 entity들의 변경사항을 데이터베이스에 반영한다(flush)
1차 캐시
- 1차 캐시의 entity의 키값은 @Id 값이다.
- 1차 캐시에 해당 entity가 없는 경우에만 DB에 값을 요청한다.
- 쓰기 지연 - 변경된 엔티티를 모아두었다가 트랜잭션 commit 할때 일괄처리함
- entityManager.merge()를 명시적으로 호출하지 않아도, 변경감지를 하기 때문에 값이 변경된 영속성 컨텍스트의 entity는 transaction이 종료되면 자동적으로 데이터베이스에 반영된다.
@DynamicUpdate, @DynamicInsert
필드가 많거나 너무 크면 수정된 데이터만을 이용한 update/Insert SQL을 생성할 수 있도록 해주는 annotaion 없으면 기본전략은 모든 컬럼에 대해 update, insert를 처리한다.
트랜잭션 범위의 영속성 컨텍스트 (spring 컨테이너)
- spring 컨테이너는 트랜잭션 범위의 영속성 컨텍스트 전략을 기본으로 사용
=> 트랜잭션별로 영속성 컨텍스트가 생성된다 (entityManager가 달라도 상관없음)
트랜잭션 격리 수준
위에서 아래로 격리수준은 높아진다.
격리 수준에 따른 문제점
- Dirty Read
트랜잭션1이 데이터를 수정중일 때, 트랜잭션2가 수정중인 데이터를 조회할 수 있음
- Non-repeatable Read (반복 불가능한 읽기)
트랜잭션1이 데이터를 조회중일 때 트랜잭션2가 데이터를 수정하고 commit하면 트랜잭션1이 데이터를 다시 조회시 수정된 데이터가 조회되어 처음 조회한 값과 다른 값이 조회됨
- Phantom Read
조건 집합에 대한 반복 조회시 결과집합이 달라지는 것
예) 트랜잭션1 : 10살 이하의 회원을 조회
트랜잭션2 : 5살 회원을 생성 후 commit
트랜잭션1의 조회결과는 처음과 달라진다.
동시성 처리를 성능을 위해 대부분의 DB의 격리수준은 Read Uncommited
낙관적 락과 비관적 락
jpa의 기본적인 트랜잭션 격리 수준 : READ COMMITED
낙관적 락
- jpa가 제공하는 버전관리기능을 사용 (데이터베이스의 락기능을 사용하지 않는다)
- 트랜잭션의 대부분이 충돌이 발생하지 않는다고 가정
- @Version 어노테이션을 사용하는 필드 필요(버전관리용)
(long, integer, short, timestamp 타입만 적용가능)
- entity의 값이 변경되면 version이 증가한다.
- update문이 실행될 때, version이 일치하는 경우만 실행된다
- 락 옵션없이 사용해도 @Version 필드가 존재하면 낙관적 락이 기본 적용된다.
비관적 락