2011-06-13 2 views
0

내 응용 프로그램에서 기본 저장 장치 개체를 인터페이스 뒤에 숨기므로 마음대로 저장소를 전환 할 수 있습니다.간단한 Pojo 데이터 개체에 대해 자동 커밋을 설정 하시겠습니까?

문제는 최대 절전 모드를 테스트 할 때 최대 절전 모드가 트랜잭션 지향적 인 것으로 보인다는 것입니다. 주제 (주로 their official docs)에서 찾을 수있는 모든 것은 자동 커밋이 좋지 않으며 거의 ​​사용되지 않아야한다고 말합니다. 그러나 내 전체 응용 프로그램은 인터페이스를 중심으로 작성된 Hibernate를 중심으로 작성되지 않았습니다. 즉, 트랜잭션이 아닌 한 메소드 (예 : 공장 출하시 getObjects()에서 데이터베이스에서 데이터를 가져 오는 경우를 의미합니다.

저장 장치 구현을 추상화 했으므로 자동 적용이 올바른 해결책입니까? 아니면 대안이 있습니까?

+1

자동 커밋을 사용했다고해서 더 이상 트랜잭션을 사용하지 않는다는 의미는 아닙니다. 각 명령문은 자체 트랜잭션에서 실행됩니다. –

+0

@Vineet 어쩌면 나는 그 말을 더 잘 표현할 수 있었다. 나는 코드의 다른 부분이 pojo 자체가 아닌 데이터 (beginTransaction(), get 또는 set, commit())를 얻기 위해 트랜잭션을 사용해야 함을 의미한다. – TheLQ

+0

음, POJO는 다른 부분이 데이터 액세스를 수행하고 POJO가 자동 커밋에 대해 걱정해야하는 이유를 추측하여 어떻게합니까? –

답변

1

자동 커밋을 사용한다고해서 더 이상 데이터 액세스에 트랜잭션이 사용되지 않는다는 의미는 아닙니다. 단순히 각 명령문이 자체 트랜잭션에서 실행된다는 것을 의미합니다. 트랜잭션이 시작될 때 정확한 인스턴스가 JDBC 사양에 정의 된대로 종료됩니다. 간결함을 위해, 이것은 일반적으로 실행되는 성명의 본질에 달려 있습니다.

디자인 구현 방법을 잘 모르겠지만 비 트랜잭션 시스템은 일반적으로 세 가지 문제가 있습니다. 자동 커밋을 사용하면 이러한 문제 중 하나 이상을 다시 유발할 수 있습니다.

더러운

엔티티를 읽고 업데이트하지만 새 값을 커밋하지 않을 응용 프로그램에서 스레드 A를 고려 읽습니다. 동일한 엔티티를 읽고 업데이트 된 값을 보는 다른 스레드 B를 고려하십시오. 스레드 A가 변경 사항을 롤백하거나 업데이트 된 값을 커밋하지 못하면 B는 본질적으로 더티 값을 사용합니다. 더티 읽기를 수행했기 때문입니다.

자체 커밋 자체가 더티 읽기가 아닙니다. 그러나 원래 단일 트랜잭션에서 수행 된 데이터베이스 읽기 - 쓰기 시퀀스가있는 경우 모든 읽기/쓰기 작업 후에 시퀀스 커밋을 수행하면 현재 트랜잭션이 단순히 롤백 될 수 있으므로 다른 트랜잭션에서 더티 읽기가 발생합니다 변화.

반복 불가의 비를 고려 트랜잭션의 컨텍스트에서 두번 동일한 엔티티 (레코드)를 판독하고, 상기 제 2 판독에 다른 값을보고, 트랜잭션의 콘텍스트에서

를 읽고 반복 읽기. 이것은 다른 트랜잭션이 변경을 커밋하고 진행중인 트랜잭션이 새 값을 읽을 때 발생합니다.

자동 커밋을 사용하거나 두 개의 다른 트랜잭션에서 읽기 작업을 수행하면 동일한 스레드의 읽기 작업이 서로 다른 트랜잭션 컨텍스트에서 실행되기 때문에 반복 불가능한 읽기가 발생할 가능성이 높습니다. 두 번째 읽기는 커밋 된 값 (다른 스레드의 트랜잭션)을 봅니다.

팬텀은 아니지만 아주, 비 반복 읽기 매우 유사

을 읽습니다. 이 경우 두 번째 읽기를 수행하는 실행 스레드는 새 레코드 형태로 추가 데이터 (업데이트되지 않은 데이터)를 보게됩니다.

마찬가지로 auto-commit을 사용하면 같은 이유로 응용 프로그램에서 팬텀 (phantom) 읽기가 발생합니다.

이러한 문제는 사용 된 데이터베이스 트랜잭션 격리 수준에 따라 다르지만 결국 ORM 프레임 워크를 사용할 때 트랜잭션 시작 및 종료 표시는 응용 프로그램 개발자에게 맡깁니다. 개별 읽기 - 쓰기 작업은 데이터베이스에 의해 서로 격리 될 수 있지만 작업이 트랜잭션 컨텍스트에서 발생하는지 확인하는 것은 개발자의 몫입니다. 자동 커밋을 사용하면 모든 작업에 대한 트랜잭션 컨텍스트가 변경됩니다. 사용

TLDR

자동 위탁 수행하는 트랜잭션 활동은 "비즈니스 트랜잭션 컨텍스트"동안 장애시 안전한 상태로 롤백을 수행하는 것은 불가능 것을 의미합니다. 이와 같은 이유로 JDBC에서 일괄 업데이트를 수행 할 때 자동 커밋을 비활성화해야합니다. 자동 커밋 (auto-commit)을 사용하면 일괄 처리가 끝날 때 커밋해야 할 때마다 일괄 처리의 모든 업데이트에 대해 커밋을 수행해야합니다.

Java Transaction Design Strategies (무료 전자 책으로 사용 가능)을 읽으면 거래 사용에 대한 더 자세한 정보를 얻을 수 있습니다.

+0

처음 두 가지는 기본적인 멀티 스레딩 동기화 문제처럼 보입니다. 내 응용 프로그램은 기본적으로 다른 스레드에 모든 리스너가있는 대규모 Event-Listener 시스템입니다. Hibernate를 어플리케이션에 깊숙이 통합하지 않고 두 가지 옵션을 볼 수 있습니다 : 1) 각 리스너가 실행되고 닫히기 전에 트랜잭션을 시작하거나 (실제로는 가능합니다) 또는 2) 자동 커밋을 사용하여 쉽게 해결할 수없는 기본 동기화 문제라고 말하면됩니다 내 응용 프로그램 디자인. 그 중 어느 것이 실행 가능한 옵션처럼 보입니까? – TheLQ

+0

@TheLQ, 귀하의 옵션 (1)은 위의 코멘트에 해당됩니다. "일반적으로 트랜잭션 리소스에 액세스하기 전에 비즈니스 로직의 진입 점에서 트랜잭션을 시작하고 모든 트랜잭션 활동을 해당 컨텍스트에서 수행하십시오." 옵션 (2)에 관한 한, 각 Listener에서 수행되는 작업에 따라 다릅니다. 자동 커밋을 사용하면 롤백 할 복구 데이터가 손실되는 경우가 많습니다. 하나의 업데이트는 성공하지만, 다른 업데이트는 실패 할 수 있습니다. 데이터베이스에서 수위 작업을 수행하게됩니다. –

+0

(1) Autocommit을 사용하여 게시 한 것과 동일한 동기화 문제가 발생하지 않았습니까? 데이터 객체는 모두 공유되며 (공유하기 어렵고 프로그램을 어떻게 다시, 그리고 왜 다시 작성 하는지를 설명하기가 어렵습니다), 상호 리소스로서 위에서 설명한 모든 문제를 볼 수 있습니다. – TheLQ

0

hibernate config XML이나 프로그래밍 방식으로 SessionFactory에서 true로 설정할 수있는 'hibernate.connection.autocommit'속성이 있습니다.

Hibernate 구현 인 getObjects() 인터페이스 메소드 내에서 트랜잭션을 시작하고 커밋하는 것보다 실제로 어떤 이점이 있는지 분명하지 않습니다.

+0

그것은 자동 커밋이 본질적으로 어떤 일을하는 것이 아닌가? – TheLQ

+0

이것은 인터페이스 방법이 무엇이고 인터페이스 방법이 얼마나되는지에 따라 다릅니다. 메소드가 많은 오브젝트를 가져 와서 여러 테이블을 갱신해야하는 경우, 어딘가에 장애가 발생하면 메소드를 롤백 할 수 있습니다. – Affe

+0

그래서 나는 대부분의 필드에서 autocommit을 사용해도 좋지만 관계 필드 (Many-To-Many + OneToMany + ManyToOne + OneToOne 관계)에 대한 자체 트랜잭션을 작성해야합니까? – TheLQ

관련 문제