트랜잭션을 지원하는 쓰기 지연과 JDBC 배치
insert(member1); // INSERT INTO ...
insert(member2); // INSERT INTO ...
insert(member3); // INSERT INTO ...
insert(member4); // INSERT INTO ...
insert(member5); // INSERT INTO ...
commit();
위와 같은 경우는 5번에 INSERT SQL과 1번의 커밋으로 총 6번 데이터베이스와 통신한다. 이것을 최적화 하려면 SQL을 모아 한 번에 데이터베이스로 보내면 된다.
JDBC가 제공하는 SQL 배치 기능을 사용하면 SQL을 모아서 데이터베이스에 한 번에 보낼 수 있다. 하지만 이 기능을 사용하려면 코드의 많은 부분을 수정해야 한다. 특히 비즈니스 로직이 복잡하게 얽혀 있는 곳에서 사용하기는 쉽지 않고 적용해도 코드가 상당히 지저분해진다. 그래서 보통 수백 수천 건 이상의 데이터를 변경하는 특수한 상환에 SQL 배치 기능을 사용한다.
JPA는 플러시 기능이 있으므로 SQL 배치 기능을 효과적으로 사용할 수 있다.
spring:
jpa:
properties:
hibernate.default_batch_fetch_size: 1000
yml 파일에 다음과 같이 설정해주면 데이터를 등록, 수정, 삭제할 때 하이버네이트는 SQL 배치 기능을 사용한다.
하지만 배치는 같은 SQL일 때만 유효하다. 중간에 다른 처리가 들어가면 SQL 배치를 다시 시작한다.
em.persist(new Member()); // SQL 배치 시작
em.persist(new Member());
em.persist(new Member());
em.persist(new Child()); // SQL 배치 재시작
em.persist(new Member()); // SQL 배치 재시작
em.persist(new Member());
트랜잭션을 지원하는 쓰기 지연과 애플리케이션 확장성
트랜잭션을 지원하는 쓰기 지연과 변경 감지 기능 덕분에 성능과 개발의 편의성 두 가지를 모두 얻을 수 있다.
하지만 진짜 장점은 트랜잭션을 커밋해서 영속성 컨텍스트를 플러시하기 전까지는 데이터 베이스에 데이터를 등록, 수정, 삭제하지 않기 때문에 데이터베이스 테이블 Row에 락(Lock)이 걸리는 시간을 최소한 한다는 점이다.
update(member); // Update SQL
비지니스로직A(); // Update SQL
비지니스로직B(); // Insert SQL
commit();
JPA를 사용하지 않고 SQL을 직접 다루면 update(member)를 호출할 때 Update SQL을 실행하면서 데이터베이스 테이블 Row에 락(Lock)을 건다. 이 락은 비지니스로직A, 비지니스로직B를 모두 수행하고 commit()을 호출할 때가지 유지된다.
트랜잭션 격리 수준에 따라 다르지만 보통 많이 사용하는 커밋된 읽기(Read Committed) 격리 수준이나 그 이상에서는 데이터베이스에 현재 수정 중인 데이터를 수정하려는 다른 트랜잭션을 락이 풀릴 때까지 대기한다.
JPA는 커밋을 해야 플러시를 호출하고 데이터베이스에 수정 쿼리를 보낸다.
예제에서 commit()을 호출할 때 Update SQL을 실행하고 바로 데이터베이스 트랜젝션을 커밋한다.
쿼리를 보내고 바로 트랜잭션을 커밋하므로 결과적으로 데이터베이스에 락이 걸리는 시간을 최소화 한다.
사용자가 증가하면 서버는 더 증설이 가능하지만, 데이터베이스 락은 애플리케이션 서버 증설만으로는 해결할 수 없다. 오히려 서버를 증설해서 트랜잭션이 증가할수록 더 많은 데이터베이스 락이 걸린다.
JPA의 쓰기 지연 기능은 데이터베이스에 락이 걸리는 시간을 최소화해서 동시에 더 많은 트랜잭션을 처리할 수 있는 장점이 있다.
'JPA' 카테고리의 다른 글
낙관적 락(Optimistic Lock)과 비관적 락(Pessimistic Lock)의 기초 (0) | 2022.01.26 |
---|---|
트랜잭션과 격리 수준 (0) | 2022.01.25 |
JPA 배치 처리 (0) | 2022.01.25 |
JPA 읽기 전용 쿼리의 성능 최적화 (0) | 2022.01.25 |
영속성 컨텍스트에 따른 엔티티 비교 (0) | 2022.01.24 |