Whiteship's Note


하이버네이트에서 Nontransactional data access

Hibernate/Chapter 10 : 2008. 4. 1. 17:11


Session session = sessionFactory.openSession();
session.get(Item.class, 123l);
session.close();
  1. Session이 열리고 이 순간 Connection을 얻어오진 않는다.
  2. get()을 호출하는 순간 Select 문을 날리는데, 이 때 Connection을 pool에서 꺼낸다. 하이버네이트는 기본으로 그 즉시 autocommit mode를 끈다. setAutoCommit(false). 이렇게 효율적으로 JDBC 트랜잭션을 시작한다.
  3. SELECT는 JDBC 트랜잭션 내부에서 실행된다. 하이버네이트는 Connection의 close()를 호출하여 Connection을 poll에 반납한다. 이 때 남아있는 트랜잭션은 어떻게 될까?
  • 사용하는 DB에 달려있다. JDBC 스펙에서는 이 것과 관련되서 정해논게 없다.
  • 오라클은 트랜잭션을 커밋한다.
  • 다른 많은 JDBC 밴더들은 트랜잭션을 롤백한다.
  • 위는 Select 문이라서 상관없지만, sequence를 가져온 다음에 INSERT은 날리지 않고 flush 될 때까지 기다린다. 그러다 그냥 끝나게 되니까 INSERT 문이 날아가지 않는다.
  • idendity 전략으로 PK를 생성할 때에는 DB에 들어가야 얻을 수 있으니까, INSERT문이 바로 날아간다.
  • 이렇게 트랜잭션 경계를 설정하지 않으면 위와 같은 일이 발생하는데, 이때에는 JDBC 커넥션을 오토커밋 모드로 설정해준다.
<property name="connection.autocommit">true</property>
  • 즉 DB Connection을 가져올 때 setAutoCommit(false) 이걸 호출하지 않는다.
top

Write a comment.


autocommit에 관한 오해

Hibernate/Chapter 10 : 2008. 4. 1. 17:11


트랜잭션 없이 쿼리를 날릴 수 있는가?

  • 트랜잭션 범위 밖에서 DB와 뭔가를 할 수가 없다. 불가능하다. 어떤 SQL 문도 DB 트랜잭션 밖에서 날릴 수는 없다.
  • nontransactional은 명시적인 트랜잭션 경계가 없다는 것이다. 시스템 트랜잭션이 없다는 것이다. 그렇게 하면 데이터에 접근할 때 autocommit 모드로 실행된다.

성능 향상

  • 잘 생각해봐야한다. 모든 SQL 문마다 트랜잭션을 열고 닫고 할 텐데 아마도 성능이 떨어질 것이다.

애플레이션 확장성 증가

  • 잘 생각해봐야한다. DB 트랜잭션이 길어지면 분명 락을 가지고 있는 시간이 길어지니까 확장성이 안 좋을 수 있다. 하지만 하이버네이트의 persistence context와 write-behind 특징을 생각해보면 모든 쓰기 락들은 매우 짧은 기간 동안만 가지고 있게 된다. isolation level을 높였을 때 사용하게 되는 읽기 락의 비용은 무시해도 좋은 수준이다. 아니면 아예 읽기 락이 아닌 multiversion concurrency를 지원하는 DB(오라클, PostgreSQL, Infomix, Firebird)를 사용하면 된다.

포기해야 하는 것들

  • SQL 문장들을 그룹핑하여 원자성을 보장하는 것이 불가능.
  • 데이터가 병렬적으로 수정될 때 isolation level이 낮아진다. repeatable read가 불가능하다.

Data Access Type

  • 보통의 트랜잭션
  • Read-only 트랜잭션
  • Nontransactional
top

Write a comment.