이 기사는 분산 트랜잭션 관리를 달성하기 위한 spring 트랜잭션 격리 수준, 전파 동작 및 spring+mybatis+atomikos에 대한 내용을 제공합니다. 도움이 필요한 친구들이 참고할 수 있기를 바랍니다. 돕다.
원자성: 즉, 트랜잭션은 분할할 수 없는 가장 작은 작업 단위이며 트랜잭션 내의 모든 작업은 완료되거나 전혀 수행되지 않습니다.
일관성: 트랜잭션에서 데이터베이스의 데이터입니다. 실행 전에는 올바른 상태에 있었지만 거래 실행이 완료된 후에도 데이터베이스의 데이터는 여전히 올바른 상태에 있어야 합니다. 즉, 은행 이체와 같은 데이터 무결성 제약 조건이 파괴되지 않고 A가 B에게 돈을 이체합니다. , A의 돈이 B로 이체되어야 함을 보장해야 합니다. A의 돈이 이체되었지만 B가 이를 받지 못하는 상황은 발생하지 않습니다. 그렇지 않으면 데이터베이스의 데이터가 일관성이 없는(잘못된) 상태가 됩니다.
Isolation: 동시 트랜잭션 실행은 서로 영향을 미치지 않습니다. 한 트랜잭션 내의 작업은 다른 트랜잭션에 영향을 미치지 않습니다. 이를 위해서는 격리를 지정하는 트랜잭션 격리 수준이 필요합니다. 성공적으로 실행되면 데이터베이스 데이터에 대한 변경 사항은 영구적이어야 하며 시스템 오류나 정전 등으로 인해 데이터 불일치나 손실이 발생하지 않아야 합니다.
2. 트랜잭션 유형
connection
을 통해 위에서 언급한 데이터베이스 트랜잭션의 로컬 트랜잭션입니다. 개체 제어 관리.JTA 트랜잭션: JTA는 Java EE 데이터베이스 트랜잭션 사양인 Java Transaction API(Java Transaction API)를 참조하며 JTA는 애플리케이션 서버 공급업체(예: WebSphere 애플리케이션)에서 구현하는 트랜잭션 관리 인터페이스만 제공합니다. 서버) JTA 트랜잭션은 JDBC보다 강력하며
분산 트랜잭션을 지원합니다프로그래밍 여부에 따라 선언적 트랜잭션과 프로그래밍적 트랜잭션으로 구분됩니다. http://blog.csdn.net/liaohaojian/article/details/70139151
3. Spring 트랜잭션 격리 수준: Spring에는 TransactionDefinition 인터페이스에 정의된 5가지 주요 격리 수준이 있습니다. 소스 코드를 보면 기본 격리_기본값(기본 데이터베이스의 기본 수준)과 다른 네 가지 격리 수준이 데이터베이스 격리 수준과 일치한다는 것을 알 수 있습니다.
ISOLATION_READ_UNCOMMITTED(커밋되지 않은 읽기): 트랜잭션이 커밋되기 전 가장 낮은 격리 수준입니다. 다른 트랜잭션에서 읽을 수 있음(팬텀 읽기, 더티 읽기, 반복 불가능한 읽기 발생)
ISOLATION_READ_COMMITTED(커밋된 읽기): 트랜잭션은 제출된 후에만 다른 트랜잭션에서 읽을 수 있습니다. 커밋되지 않은 트랜잭션의 데이터를 읽는 것부터 팬텀 읽기 및 반복 불가능한 읽기가 계속 발생함), SQL Server 기본 수준
ISOLATION_REPEATABLE_READ(반복 읽기) : 반복 가능한 읽기, 동일한 데이터를 읽을 때 보장 여러 번 그 값이 트랜잭션 시작 부분의 내용과 일치하며 다른 트랜잭션의 커밋되지 않은 데이터를 읽는 것이 금지됩니다. (이러한 격리는 기본적으로 더티 읽기 및 반복 불가능한 읽기를 방지할 수 있습니다(수정에 중점을 둡니다) , 그러나 팬텀 읽기가 발생합니다(증가 및 삭제에 중점을 둡니다)) (MySql 기본 수준, 트랜잭션 격리 수준 설정을 통해 변경합니다
)ISOLATION_SERIALIZABLE(직렬화): 가장 비싸고 가장 안정적인 격리 수준(이 격리 수준은 더티 읽기 및 반복 불가능한 읽기, 팬텀 읽기를 방지할 수 있음)
업데이트 손실: 두 트랜잭션이 동시에 데이터 행을 업데이트하면 첫 번째 트랜잭션의 업데이트가 덮어쓰기되어 첫 번째 트랜잭션에서 업데이트된 데이터가 손실됩니다.
팬텀 읽기: 동일한 트랜잭션 작업 중에 동일한 데이터가 서로 다른 기간에 여러 번(다른 트랜잭션) 읽혀지며 읽은 내용이 일치하지 않습니다(일반적으로 행 수가 다소 줄어듭니다). ).
더티 읽기(Dirty Read): 트랜잭션은 트랜잭션에서 언급되지 않은 다른 트랜잭션의 내용을 읽습니다. 이를 더티 읽기(Dirty Read)라고 합니다.
비반복 읽기: 동일한 트랜잭션에서 여러 번 읽은 내용이 일관성이 없습니다(일반적으로 행 수는 동일하게 유지되지만 내용은 변경됩니다).
팬텀 읽기와 비반복 읽기의 차이점: 팬텀 읽기의 초점은 삽입 및 삭제입니다. 즉, 두 번째 쿼리는 첫 번째 쿼리보다 데이터가 적거나 많음을 알게 되므로 반복 불가능한 읽기의 핵심은 수정입니다. 즉, 두 번째 쿼리에서는 쿼리 결과가 첫 번째 쿼리 결과와 일치하지 않는다는 사실을 알게 됩니다. 즉, 첫 번째 결과는 더 이상 재현할 수 없습니다.
데이터베이스 격리 수준이 높을수록 실행 비용이 높아지고 동시 실행 성능이 저하됩니다. 따라서 실제 프로젝트를 개발하고 사용할 때는 종합적인 고려가 필요합니다. 동시성 성능을 고려하려면 일반적으로 커밋을 사용하세요. 업데이트 손실을 방지할 수 있는 읽기 격리 수준 및 더티 읽기(비반복 읽기 및 팬텀 읽기는 피할 수 없음)는 가능하면 비관적 잠금 또는 낙관적 잠금을 사용하여 이러한 문제를 해결할 수 있습니다.
PROPAGATION_REQUIRED: 현재 트랜잭션을 지원합니다. 현재 트랜잭션이 없으면 새 트랜잭션을 만듭니다.
PROPAGATION_SUPPORTS: 현재 트랜잭션이 없으면 비트랜잭션으로 실행됩니다(소스 코드에 명확하지 않은 메모가 있으며 나중에 연구할 예정입니다).
PROPAGATION_MANDATORY: 현재 트랜잭션을 지원합니다. 현재 트랜잭션이 없으면 예외가 발생합니다(기존 트랜잭션에서 실행되어야 하며 비즈니스 메서드는 자체 트랜잭션을 단독으로 시작할 수 없습니다).
PROPAGATION_REQUIRES_NEW: 항상 새 거래를 생성하세요. 현재 거래가 있는 경우 원래 거래가 일시 중지됩니다.
PROPAGATION_NOT_SUPPORTED: 현재 트랜잭션이 지원되지 않으며 항상 비트랜잭션 방식으로 실행됩니다. 현재 트랜잭션이 존재하는 경우 트랜잭션이 일시 중지됩니다.
PROPAGATION_NEVER: 현재 트랜잭션이 지원되지 않습니다. 현재 트랜잭션이 존재하는 경우 예외가 발생합니다.
PROPAGATION_NESTED: 현재 트랜잭션이 있으면 중첩 트랜잭션에서 실행됩니다. 현재 트랜잭션이 없으면 PROPAGATION_REQUIRED와 유사한 작업이 실행됩니다. (참고: JDBC에 적용할 경우 JDBC 3.0 또는 위의 드라이버가 적용 가능합니다).
1.spring은 다양한 데이터 소스를 지원하기 위해 많은 내장 트랜잭션 관리자를 제공합니다. 세 가지 공통 카테고리가 있습니다
DataSourceTransactionManager: org.springframework.jdbc.datasource 패키지에서 데이터 소스 트랜잭션 관리 클래스는 단일 javax.sql.DataSource 데이터 소스에 대한 트랜잭션 관리를 제공합니다. JDBC, Mybatis 프레임워크 트랜잭션 관리에 사용됩니다.
HibernateTransactionManager: org.springframework.orm.hibernate3 패키지에서 데이터 소스 트랜잭션 관리 클래스는 단일 org.hibernate.SessionFactory 트랜잭션에 대한 지원을 제공하며 Hibernate 프레임워크를 통합할 때 트랜잭션 관리에 사용됩니다. 이 트랜잭션 관리자는 Hibernate3+ 버전만 지원하고 Spring3.0+ 버전은 Hibernate 3.2+ 버전만 지원합니다.
JtaTransactionManager: org.springframework.transaction.jta 패키지에 위치, 분산 트랜잭션 관리 제공 트랜잭션 관리를 지원하고 Java EE 애플리케이션 서버에 위임하거나 로컬 JTA 트랜잭션 관리자를 사용자 정의하여 애플리케이션에 중첩합니다.
내장 트랜잭션 관리자는 모두 추상 클래스 AbstractPlatformTransactionManager를 상속하고 AbstractPlatformTransactionManager는 PlatformTransactionManager 인터페이스를 상속합니다.
트랜잭션 관리를 위한 Spring 프레임워크 지원의 핵심은 트랜잭션 관리자 추상화입니다. PlatformTransactionManager 인터페이스가 구현되어 여러 데이터 액세스 프레임워크의 트랜잭션 관리를 지원할 수 있습니다.
PlatformTransactionManager 인터페이스는 다음과 같이 정의됩니다
TransactionStatus 인터페이스는 다음과 같이 정의됩니다:public interface TransactionStatus extends SavepointManager { boolean isNewTransaction(); //返回当前事务是否是新的事务 boolean hasSavepoint(); //返回当前事务是否有保存点 void setRollbackOnly(); //设置事务回滚 boolean isRollbackOnly(); //设置当前事务是否应该回滚 void flush(); //用于刷新底层会话中的修改到数据库,一般用于刷新如Hibernate/JPA的会话,可能对如JDBC类型的事务无任何影响; boolean isCompleted(); //返回事务是否完成 }로그인 후 복사2. Spring 분산 트랜잭션 구성
은 Tomcat과 같은 애플리케이션 서버의 JNDI 데이터 소스를 참조하고 JTA 트랜잭션 관리를 간접적으로 구현하며 애플리케이션 서버에 의존합니다.
JOTM(공식 웹사이트: http://jotm.objectweb.org/)을 직접 통합하기 위해 Atomikos(공식 웹사이트: https://www.atomikos.com/)는 JTA 트랜잭션 관리를 제공합니다(애플리케이션 서버 지원 없음, 단위 테스트에 자주 사용됨)
특정 사용 응용 서버의 트랜잭션 관리자는 JTA 트랜잭션의 고급 기능(Weblogic, Websphere)을 사용합니다.
1) 응용 서버의 JNDI 데이터 소스를 참조합니다. Tomcat 등) JTA 트랜잭션 관리를 간접적으로 구현하기 위한 구성은 다음과 같습니다.
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:jee="http://www.springframework.org/schema/jee" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/jee http://www.springframework.org/schema/jee/spring-jee-3.0.xsd"> <!-- JNDI数据源 --> <jee:jndi-lookup id="dataSource" jndi-name="jdbc/test"/> <!-- JTA事务管理器 --> <bean id="txManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <!--transactionManagerName指定JTA事务管理器的JNDI名字,从而将事务管理委托给该事务管理器 --> <property name="transactionManagerName" value="java:comp/TransactionManager"/> </bean> </beans>로그인 후 복사2 ) Atomikos를 사용하여 분산 트랜잭션 관리를 구현하면 구성은 다음과 같습니다.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p" xmlns:aop="http://www.springframework.org/schema/aop" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context" xmlns:task="http://www.springframework.org/schema/task" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd" > <context:component-scan base-package="com.suicai.*.service.impl" /> <context:component-scan base-package="com.suicai.util" /> <!-- 此方法加载的配置文件仅仅在xml中使用,但是工具类都采用注解的方式 --> <bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location" value="classpath:conn.properties" /> </bean> <!-- 仅仅支持注解不支持在xml配置中使用properties文件 在类中可以使用SPEL表达式来加载相应的值 --> <bean id="temp" class="org.springframework.beans.factory.config.PropertiesFactoryBean"> <property name="locations"> <array> <value>classpath:public.properties</value> </array> </property> </bean> <bean id="abstractXADataSource" class="com.atomikos.jdbc.AtomikosDataSourceBean" init-method="init" destroy-method="close" abstract="true"> <property name="borrowConnectionTimeout" value="60"/> <!--获取连接失败重新获等待最大时间,在这个时间内如果有可用连接,将返回--> <property name="reapTimeout" value="20"/> <!--最大获取数据时间,如果不设置这个值,Atomikos使用默认的5分钟,那么在处理大批量数据读取的时候,一旦超过5分钟,就会抛出类似 Resultset is close 的错误.--> <property name="maintenanceInterval" value="60" /> <!--连接回收时间--> <property name="loginTimeout" value="60" /> <!--java数据库连接池,最大可等待获取datasouce的时间--> <property name="logWriter" value="60"/> <property name="minPoolSize" value="1" /> <!-- 连接池中保留的最小连接数 --> <property name="maxPoolSize" value="3" /> <!-- 连接池中保留的最大连接数 --> <property name="maxIdleTime" value="60" /> <!-- 最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 --> </bean> <!-- 配置2个数据源 mysql --> <bean id="ds_suicai" parent="abstractXADataSource"> <!-- uniqueResourceName表示唯一资源名,如有多个数据源不可重复; --> <property name="uniqueResourceName" value="suicaifortest" /> <!-- xaDataSourceClassName是具体分布式数据源厂商实现; --> <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/> <!-- xaProperties属性指定具体厂商数据库属性 --> <property name="xaProperties"> <props> <prop key="URL">${db.jdbcUrlOne}</prop> <prop key="user">${user}</prop> <prop key="password">${password}</prop> </props> </property> </bean> <bean id="ds_kaizhi" parent="abstractXADataSource"> <!-- uniqueResourceName表示唯一资源名,如有多个数据源不可重复; --> <property name="uniqueResourceName" value="puildingpurchasefortest" /> <!-- xaDataSourceClassName是具体分布式数据源厂商实现; --> <property name="xaDataSourceClassName" value="com.mysql.jdbc.jdbc2.optional.MysqlXADataSource"/> <!-- xaProperties属性指定具体厂商数据库属性 --> <property name="xaProperties"> <props> <prop key="URL">${db.jdbcUrlTwo}</prop> <prop key="user">${user}</prop> <prop key="password">${password}</prop> </props> </property> </bean> <!-- 动态配置数据源 --> <bean id="dataSource2" class="com.suicai.common.datasource.DynamicDataSource"> <property name="targetDataSources"> <map key-type ="java.lang.String"> <entry value-ref ="ds_suicai" key="ds_suicai"></entry > <entry value-ref ="ds_kaizhi" key="ds_kaizhi"></entry > </map > </property> <property name ="defaultTargetDataSource" ref="ds_suicai"></property> </bean> <bean id ="sqlSessionFactoryBeanA" class="org.mybatis.spring.SqlSessionFactoryBean" > <!-- 指定数据源 --> <property name ="dataSource" ref="ds_suicai" /> <!-- 指定mybatis 的配置文件 --> <property name ="configLocation" value="classpath:mybatis.cfg.xml" /> </bean> <bean id ="sqlSessionFactoryBeanB" class="org.mybatis.spring.SqlSessionFactoryBean" > <!-- 指定数据源 --> <property name ="dataSource" ref="ds_kaizhi" /> <!-- 指定mybatis 的配置文件 --> <property name ="configLocation" value="classpath:mybatis.cfg.xml" /> </bean> <!--CustomSqlSessionTemplate继承SqlSessionTemplate重写getSqlSessionFactory方法,具体请下载查看--> <bean id="sqlSessionTemplate" class="com.suicai.util.CustomSqlSessionTemplate" scope="prototype"> <constructor-arg ref="sqlSessionFactoryBeanA" /> <property name="targetSqlSessionFactorys"> <map> <entry value-ref ="sqlSessionFactoryBeanA" key="ds_suicai1"></entry > <entry value-ref ="sqlSessionFactoryBeanB" key="ds_kaizhi1"></entry > </map> </property> </bean> <!-- 配置atomikos事务管理器 --> <bean id="atomikosTransactionManager" class = "com.atomikos.icatch.jta.UserTransactionManager" init-method="init" destroy-method = "close"> <property name="forceShutdown" value="true"/> </bean> <bean id="atomikosUserTransaction" class="com.atomikos.icatch.jta.UserTransactionImp"></bean> <!-- 配置spring事务管理器 --> <bean id="transactionManager" class="org.springframework.transaction.jta.JtaTransactionManager"> <property name="transactionManager"> <ref bean="atomikosTransactionManager"/> </property> <property name="userTransaction"> <ref bean="atomikosUserTransaction"/> </property> <!-- 必须设置,否则程序出现异常 JtaTransactionManager does not support custom isolation levels by default --> <property name="allowCustomIsolationLevels" value="true"/> </bean> <tx:advice id="advice" transaction-manager="transactionManager"> <tx:attributes> <!-- REQUIRED:必须要有事务, 如果没有就在上下文创建一个 --> <tx:method name="save*" propagation="REQUIRED"/> <tx:method name="creat*" propagation="REQUIRED"/> <tx:method name="add*" propagation="REQUIRED"/> <tx:method name="update*" propagation="REQUIRED"/> <tx:method name="delete*" propagation="REQUIRED"/> <!-- 支持,如果有就有,没有就没有 --> <tx:method name="*" propagation="SUPPORTS"/> </tx:attributes> </tx:advice> <aop:config> <aop:pointcut expression="execution(* com.suicai.*.service.impl.*.*(..))" id="pointcut"/> <!-- 吧 tx与aop的配置关联,才是完整的声明事务配置 --> <aop:advisor advice-ref="advice" pointcut-ref="pointcut"/> </aop:config> <!-- 采用包扫描机制,自动会把指定的包里面的所有dao注册 --> <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <!-- 注意注入sqlSessionTemplate --> <property name="sqlSessionTemplateBeanName" value="sqlSessionTemplate"/> <property name="basePackage" value="com.suicai.*.dao" /> </bean> <bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver"> <property name="viewClass"> <value>org.springframework.web.servlet.view.InternalResourceView</value> </property> <!--jsp存放的目录--> <property name="prefix"> <value>/</value> </property> <!--jsp文件的后缀--> <property name="suffix"> <value>.jsp</value> </property> </bean> <!-- 验证码 --> <bean id="captchaProducer" class="com.google.code.kaptcha.impl.DefaultKaptcha"> <property name="config"> <bean class="com.google.code.kaptcha.util.Config"> <constructor-arg> <props> <prop key="kaptcha.border">no</prop> <prop key="kaptcha.border.color">105,179,90</prop> <prop key="kaptcha.textproducer.font.color">red</prop> <prop key="kaptcha.image.width">200</prop> <prop key="kaptcha.textproducer.font.size">60</prop> <prop key="kaptcha.image.height">80</prop> <prop key="kaptcha.session.key">code</prop> <prop key="kaptcha.textproducer.char.length">4</prop> <prop key="kaptcha.textproducer.font.names">宋体,楷体,微软雅黑</prop> </props> </constructor-arg> </bean> </property> </bean> <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource"> <property name="basename" value="classpath:messages"/> <property name="fileEncodings" value="utf-8"/> <property name="cacheSeconds" value="120"/> </bean> </beans>로그인 후 복사위 내용은 Spring 트랜잭션 격리 수준, 전파 동작 및 spring+mybatis+atomikos는 분산 트랜잭션 관리를 실현합니다.의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!