1. 거래의 기본 원칙
스프링 트랜잭션의 본질은 실제로 데이터베이스의 거래 지원입니다. 데이터베이스 트랜잭션 지원이 없으면 Spring은 트랜잭션 기능을 제공 할 수 없습니다. 순수한 JDBC 운영 데이터베이스의 경우 트랜잭션을 사용하려면 다음 단계를 수행 할 수 있습니다.
1. 연결 연결 연결 Con = DriverManager.getConnection ()
2. 트랜잭션 콘을 엽니 다.
3. Crud를 실행하십시오
4. 거래 / 롤백 트랜잭션 Con.Commit () / con.rollback ();
5. 연결을 닫습니다. conn.close ();
Spring의 트랜잭션 관리 기능을 사용한 후에는 더 이상 2 단계와 4 단계에서 코드를 쓸 수 없지만 Spirng에 의해 자동으로 수행됩니다. 그렇다면 우리가 쓰는 CRUD 전후에 Spring은 어떻게 열리고 폐쇄 된 거래입니까? 이 문제를 해결함으로써 Spring의 거래 관리의 구현 원칙을 전체에서 이해할 수 있습니다. 주석 메소드를 예제로 간단히 소개하겠습니다.
1. 구성 파일에서 주석 드라이버를 켜고 관련 클래스 및 메소드에 @transactional에 주석을 달아 식별하십시오.
2. 스프링이 시작되면 관련 콩을 구문 분석하고 생성합니다. 이 시점에서는 관련 주석이있는 클래스와 메소드를 확인하고 이러한 클래스 및 메소드에 대한 프록시를 생성하고 @Transaction의 관련 매개 변수를 기반으로 관련 구성 주입을 수행하여 관련 트랜잭션이 프록시에서 처리되도록합니다 (정상 트랜잭션 시작 및 예외 롤백 트랜잭션).
3. 실제 데이터베이스 계층의 트랜잭션 커밋 및 롤백은 Binlog 또는 Redo Log를 통해 구현됩니다.
2. 스프링 트랜잭션의 전파 특성
스프링 트랜잭션의 소위 전파 속성은 스프링이 여러 거래가 동시에 존재할 때 여러 거래의 동작을 어떻게 처리 해야하는지 정의합니다. 이러한 속성은 TransactionDefinition에서 정의됩니다. 특정 상수는 다음 표에 설명되어 있습니다.
III. 데이터베이스 격리 수준
Dirty Reading : 하나의 트랜잭션은 데이터를 추가, 삭제 및 수정하지만 커밋되지 않으며 다른 트랜잭션은 커밋되지 않은 데이터를 읽을 수 있습니다. 이 시점에서 첫 번째 트랜잭션이 롤백되면 두 번째 트랜잭션은 더러운 데이터를 읽습니다.
반복적 인 읽기 없음 : 한 번의 거래에서 두 개의 읽기 작업이 발생합니다. 첫 번째 읽기 작업과 두 번째 작업 사이에서 다른 트랜잭션은 데이터를 수정합니다. 이 시점에서 두 번 읽은 데이터는 일치하지 않습니다.
판타지 독서 : 첫 번째 트랜잭션은 특정 범위의 배치로 데이터를 수정하고 두 번째 트랜잭션은이 범위에 하나의 데이터를 추가합니다. 현재 첫 번째 트랜잭션은 새로 추가 된 데이터의 수정을 잃게됩니다.
요약 :
격리 수준이 높을수록 데이터의 무결성과 일관성을 더 많이 보장 할 수 있지만 동시성 성능에 미치는 영향은 커집니다.
대부분의 데이터베이스의 기본 격리 수준은 SQLServer 및 Oracle과 같은 시운전됩니다.
몇몇 데이터베이스의 기본 격리 수준은 다음과 같습니다. 반복 가능한 읽기 예를 들어 : mysql innodb
IV. 봄의 격리 수준
V. 거래의 중첩
위의 이론적 지식을 통해 데이터베이스 트랜잭션 및 스프링 트랜잭션의 일부 속성과 특성을 대략 이해합니다. 다음으로, 우리는 일부 중첩 트랜잭션 시나리오를 분석하여 스프링 트랜잭션 전파의 메커니즘을 깊이 이해합니다.
외부 트랜잭션 서비스의 메소드 a ()가 내부 서비스 b의 메소드 B ()를 호출한다고 가정합니다.
propagation_required (스프링 기본값)
Serviceb.Methodb ()의 트랜잭션 수준이 propagation_required로 정의되면 servicea.methoda ()가 실행되면 트랜잭션은 이미 봄에 시작되었습니다. 현재 serviceb.methodb ()가 호출됩니다. ServiceB.Methodb ()는 Servicea.Methoda ()의 거래 내부에서 실행 중이며 새로운 트랜잭션이 시작되지 않았다는 것을 알 수 있습니다.
serviceb.methodb ()가 실행 중이면 트랜잭션 자체에 할당됩니다.
이러한 방식으로, servicea.methoda ()에서 예외가 발생하거나 serviceb.methodb () 내의 어느 곳에서나 트랜잭션이 롤백됩니다.
propagation_requires_new
예를 들어, servicea.methoda ()는 transaction_required의 트랜잭션 수준을 가지고 있으며 serviceb.methodb ()는 propagation_requires_new의 트랜잭션 수준을 갖습니다.
그런 다음 serviceb.methodb ()가 실행되면 servicea.methoda ()가 위치한 트랜잭션이 정지되고 ServiceB.Methodb ()가 새 트랜잭션을 시작하고 ServiceB.Methodb () 트랜잭션이 완료된 후에도 계속 실행됩니다.
그의 거래와 propagation_required의 차이점은 거래의 롤백 정도입니다. serviceb.methodb ()는 새로운 트랜잭션이므로 두 가지 다른 트랜잭션이 있습니다. serviceb.methodb ()가 제출 된 경우 servicea.methoda ()가 롤백에 실패하면 ServiceB.Methodb ()는 롤백하지 않습니다. serviceb.methodb ()가 롤백에 실패하면 servicea.methoda ()에 의해 던져진 예외가 잡히면 servicea.methoda () 트랜잭션이 여전히 제출 될 수 있습니다 (주로 B로 던져진 예외가 Will Rollback의 예외인지에 따라 다름).
propagation_supports
Serviceb.Methodb ()의 트랜잭션 수준이 propagation_supports라고 가정하면 servicea.methoda ()가 트랜잭션을 개설 한 것으로 밝혀지면 현재 트랜잭션에 참여할 것입니다. Servicea.methoda ()가 거래를 시작하지 않은 것으로 밝혀지면 거래 자체가 시작되지 않습니다. 이 시점에서 내부 방법의 트랜잭션은 전적으로 가장 바깥 쪽 트랜잭션에 따라 다릅니다.
propagation_nested
상황이 더욱 복잡해지고 있습니다. serviceb.methodb ()의 트랜잭션 속성은 propagation_nested로 구성됩니다. 현재 두 사람은 어떻게 협력 할 것인가? Serviceb#methodb 롤백 인 경우 내부 트랜잭션 (예 : Serviceb#Methodb)이 실행되기 전에 SavePoint로 롤백하는 반면 외부 트랜잭션 (예 : Servicea#Methoda)은 다음과 같은 두 가지 처리 방법을 가질 수 있습니다.
에이. 예외를 포착하고 예외 분기 로직을 실행하십시오
void methoda () {try {serviceb.methodb (); } catch (somexception) {// servicec.methodc ()와 같은 다른 비즈니스를 실행합니다. }} 이 방법은 중첩 거래에서 가장 귀중한 것입니다. 지점 실행의 역할을 수행합니다. serviceb.methodb가 실패하면 servicec.methodc ()가 실행되고 serviceb.methodb가 실행되기 전에 SavePoint로 롤백되므로 더러운 데이터가 생성되지 않습니다 (이 방법과 동일). 이 기능은 일부 특수 서비스에서 사용될 수 있으며 Propagation_Required 또는 Propagation_Requires_new가이를 수행 할 수 없습니다.
비. 외부 트랜잭션 롤백/커밋 코드는 수정하지 않습니다. 내부 트랜잭션 (Serviceb#Methodb) 롤백이있는 경우, 첫 번째 ServiceB.MethODB는 SavePoint를 실행하기 전에 SAVEPOINT로 롤백하며 외부 트랜잭션 (예 : Servicea#Methoda)은 특정 구성에 따라 커밋 또는 롤백 여부를 결정합니다.
다른 세 가지 트랜잭션 전파 속성은 기본적으로 비효율적이므로 여기서는 분석이 수행되지 않습니다.
6. 요약
프로젝트에서 거래가 필요한 장소의 경우 개발자가 Spring의 TransactionCallback 인터페이스를 사용하여 트랜잭션을 구현해야합니다. 스프링 트랜잭션 주석을 맹목적으로 사용하지 마십시오. 주석을 사용해야하는 경우 전파 메커니즘과 스프링 트랜잭션의 격리 수준에 대한 자세한 이해가 있어야합니다. 그렇지 않으면 예상치 못한 효과가 발생할 수 있습니다.