읽기 전용 작업을 위해 Hibernate에서 트랜잭션이 필요한 이유는 무엇입니까?


107

읽기 전용 작업을 위해 Hibernate에서 트랜잭션이 필요한 이유는 무엇입니까?

다음 트랜잭션은 DB에 잠금을 설정합니까?

DB에서 가져 오는 예제 코드 :

Transaction tx = HibernateUtil.getCurrentSession().beginTransaction(); // why begin transaction?
//readonly operation here

tx.commit() // why tx.commit? I don't want to write anything

session.close() 대신 사용할 수 있습니까 tx.commit()?


9
트랜잭션은 DB 자체에서 필요합니다. 현재 자동 커밋 모드에 대해 읽을 수 있습니다 community.jboss.org/wiki/...
Bhesh 구룽

@BheshGurung 나는 우리가 쓰기 작업을 위해서만 transcation이 필요하다고 생각한다
user93796

4
링크에서 "Debunking auto-commit myths"부분을 읽었습니까?
Bhesh Gurung 2012

답변:


131

실제로 트랜잭션을 읽기 전용으로 표시 할 이유가있을 수 있습니다.

  1. 읽기를위한 트랜잭션은 실제로 이상하게 보일 수 있으며 종종 사람들은이 경우 트랜잭션에 대한 메서드를 표시하지 않습니다. 그러나 JDBC는 어쨌든 트랜잭션을 생성합니다. autocommit=true다른 옵션이 명시 적으로 설정되지 않은 경우 작동 합니다.
  2. 그러나 메서드가 데이터베이스에 쓰지 않는다는 보장은 없습니다. 메소드를으로 표시하면 @Transactional(readonly=true)Spring은 JDBC 트랜잭션을 읽기 전용 모드로 설정하므로이 트랜잭션의 범위 에서 실제로 DB에 쓸 수 있는지 여부를 지시합니다 . 아키텍처가 번거롭고 일부 팀 구성원이 예상치 못한 위치에 수정 쿼리를 넣도록 선택할 수있는 경우이 플래그는 문제가있는 위치를 가리 킵니다.
  3. 또한 읽기 전용 트랜잭션은 DB에 의해 최적화 될 수 있지만 이것은 물론 DB에 따라 다릅니다. 예를 들어 MySQL은 5.6.4 버전부터 InnoDB에서만 이에 대한 지원을 추가했습니다.
  4. JDBC를 직접 사용하지 않고 ORM을 사용하는 경우 문제가 될 수 있습니다. 예를 들어 Hibernate 커뮤니티는 트랜잭션 외부에서 작업하면 예측할 수없는 동작이 발생할 수 있다고 말합니다. Hibernate는 트랜잭션을 열지 만 스스로 닫지는 않을 것이기 때문에 트랜잭션이 커밋되지 않은 상태에서 Connection Pool로 연결이 반환됩니다. 그러면 어떻게됩니까? JDBC는 침묵을 유지하므로 구현에 따라 다릅니다 (MySQL은 트랜잭션을 롤백하고 Oracle은이를 커밋합니다). 이는 또한 연결 풀 수준에서 구성 할 수 있습니다 (예 : C3P0은 이러한 옵션을 제공하며 기본적으로 롤백 됨).
  5. Hibernate와 관련하여 또 다른 점은 Spring은 읽기 전용 트랜잭션의 경우 FlushMode를 MANUAL로 설정하여 더티 검사가 필요없는 다른 최적화로 이어집니다.
  6. 트랜잭션 격리 수준을 재정의하거나 명시 적으로 설정할 수 있습니다. 커밋되지 않은 변경 사항을 읽거나 원하지 않기 때문에 읽기 트랜잭션에도 영향을 미치며 팬텀 읽기 등에 노출됩니다.

요약하자면 두 가지 방법을 모두 사용할 수 있지만 결과를 이해해야합니다.


회신 해 주셔서 감사합니다. 저는 최대 절전 모드 (jpa가 아닌 기본 최대 절전 모드)를 사용하고 있습니다.하지만 최대 절전 모드는 db 작업을 수행하기 전에 트랜잭션을 시작하도록 강요합니다. 시작하지 않으면 활성 추적이 없다는 오류가 발생합니다 .n. 트랜잭션을 읽기 전용으로 표시 할 수 있습니까? , 그렇다면 어떻게?
user93796

readonly 플래그는 실제로 트랜잭션 자체가 아닌 연결을 위해 설정되며 Hibernate를 통해 액세스 할 수 없습니다. Spring Transaction 지원을 사용하고 주석 또는 XML 기반 트랜잭션 구성을 사용해야합니다. 그렇게함으로써 Spring은 Hibernate 대신 연결 및 트랜잭션 관리의 소유권을 갖습니다.
Stanislav Bashkyrtsev

1
아주 잘 설명했습니다! Mark Richards의 또 다른 기사는 Transactional 주석 ( ibm.com/developerworks/java/library/j-ts1/index.html) 에서 읽기 전용 플래그의 함정을 잘 설명합니다 .
Mahesh

48

모든 데이터베이스 문은 트랜잭션 경계 (BEGIN / COMMIT / ROLLBACK)를 명시 적으로 선언하지 않은 경우에도 물리적 트랜잭션의 컨텍스트 내에서 실행됩니다 .

트랜잭션 경계를 명시 적으로 선언하지 않으면 각 문을 별도의 트랜잭션 ( autocommit모드) 에서 실행해야합니다 . 환경이 스레드 당 연결 바인딩을 처리 할 수없는 경우 문당 하나의 연결을 열고 닫을 수도 있습니다.

서비스를 선언 @Transactional하면 전체 트랜잭션 기간 동안 하나의 연결이 제공되며 모든 문은 해당 단일 격리 연결을 사용합니다. 이것은 애초에 명시 적 트랜잭션을 사용하지 않는 것보다 낫습니다.

대규모 애플리케이션에서는 동시 요청이 많을 수 있으며 데이터베이스 연결 획득 요청 속도를 줄이면 전체 애플리케이션 성능이 확실히 향상됩니다.

JPA는 읽기 작업에 트랜잭션을 적용하지 않습니다. 트랜잭션 컨텍스트를 시작하는 것을 잊은 경우 쓰기 만 트랜잭션 필수 예외를 throw합니다. 그럼에도 불구하고 읽기 전용 트랜잭션의 경우에도 트랜잭션 경계를 선언하는 것이 항상 더 좋습니다 (Spring @Transactional에서는 성능상의 이점이있는 읽기 전용 트랜잭션을 표시 할 수 있음).


1
"... 그러면 각 문은 별도의 트랜잭션에서 실행되어야합니다." 컨테이너가 일괄 처리를 자동으로 수행하지 않습니까?
아라 쉬

일괄 처리는 데이터 읽기가 아닌 수정을위한 것입니다. 그럼에도 불구하고 JPA 및 Hibernate를 사용할 때 JDBC 일괄 처리 는 기본적으로 활성화되지 않습니다.
Vlad Mihalcea

1
감사합니다 Vlad. 나는 당신의 기사 중 일부를 읽었습니다. 정말 유용합니다.
Arash

stackoverflow.com/q/34797480/179850 은 읽기 전용 트랜잭션이 성능상의 이점이 크다는 귀하의 단언과 약간 모순되는 것 같습니다. 적어도 최대 절전 모드의 경우에는 그렇지 않은 것 같습니다.
nimai

아니요, 그렇지 않습니다. 그것은 읽기 전용으로 설정하는 것이고 내 것은 자동 커밋을 피하는 것입니다.
Vlad Mihalcea

17

트랜잭션은 실제로 데이터베이스에 잠금을 설정합니다. 좋은 데이터베이스 엔진은 현명한 방식으로 동시 잠금을 처리하며, 다른 트랜잭션이 뷰를 일관성있게 만드는 데이터를 추가 하지 않도록하기 위해 읽기 전용 사용에 유용합니다 . 당신은 항상 트랜잭션을 원합니다 (때로는 격리 수준을 조정하는 것이 합리적이지만 처음에는 그렇게하지 않는 것이 가장 좋습니다). 트랜잭션 중에 DB에 쓰지 않으면 트랜잭션 커밋과 롤백 모두 동일하게 작동합니다 (매우 저렴합니다).

이제 운이 좋으며 DB에 대한 쿼리가 ORM이 항상 단일 SQL 쿼리에 매핑하는 경우 DB의 내장 자동 커밋 동작에 의존하여 명시 적 트랜잭션 없이 벗어날 수 있지만 ORM은 비교적 복잡한 시스템입니다. 따라서 구현이 실제로 수행하는 작업을 확인하는 더 많은 작업을 수행하지 않는 한 이러한 동작에 의존하는 것은 전혀 안전하지 않습니다. 명시적인 트랜잭션 경계를 작성하는 것이 훨씬 더 쉽습니다 (특히 AOP 또는 유사한 ORM 기반 기술로 수행 할 수있는 경우; Java 7부터 try-with-resources도 사용할 수 있다고 생각합니다).


14

다른 데이터베이스 클라이언트가 결과 집합을 변경하는 데이터를 쓰려고 할 수 있으므로 데이터베이스는 여전히 결과 집합을 추적해야합니다.

나는 거대한 데이터베이스 시스템을 죽이는 결함이있는 프로그램을 보았다. 왜냐하면 그들은 데이터를 읽기만하고 커밋하지 않기 때문에 트랜잭션 로그가 커지도록하기 때문이다. DB가 COMMIT 또는 ROLLBACK 전에 트랜잭션 데이터를 해제 할 수 없기 때문이다. 클라이언트가 아무것도하지 않았더라도 몇 시간 동안.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.