Home  >  Article  >  Database  >  Spring transaction isolation level, propagation behavior and spring+mybatis+atomikos realize distributed transaction management

Spring transaction isolation level, propagation behavior and spring+mybatis+atomikos realize distributed transaction management

坏嘻嘻
坏嘻嘻Original
2018-09-15 11:04:582286browse

The content of this article is about spring transaction isolation level, propagation behavior and spring mybatis atomikos implementation of distributed transaction management. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to you. help.

1. Definition of transaction: A transaction refers to a collection of multiple operating units. The operations of multiple units are indivisible as a whole. Either the operations are unsuccessful or they are all successful. It must follow four principles (ACID).

  1. Atomicity: That is, a transaction is an indivisible smallest unit of work, and all operations within the transaction are either done or none;

  2. Consistency : The data in the database is in the correct state before the transaction is executed, and the data in the database should still be in the correct state after the transaction is completed. , that is, the data integrity constraint has not been destroyed; such as bank transfer, A transfers money to B, it must be guaranteed that A's money must be transferred to B, and there will never be a situation where A's money is transferred but B does not receive it, otherwise the data in the database will be inconsistent. (incorrect) status.

  3. Isolation : The execution of concurrent transactions does not affect each other. Operations within one transaction have no impact on other transactions. This requires transactions Isolation level to specify isolation;

  4. Durability (Durability) : Once a transaction is successfully executed, its changes to the database data must be permanent and will not Data inconsistency or loss may occur due to, for example, system failure or power outage.

2. Types of transactions

  1. The database is divided into local transactions and global transactions

  • Local transactions: ordinary transactions, independent of a database, which can guarantee the ACID of operations on the database.

  • Distributed transactions: transactions involving two or more database sources, that is, transactions spanning multiple databases of the same type or heterogeneous types (composed of local transactions of each database), distributed The purpose of formal transactions is to ensure the ACID of all operations of these local transactions, so that transactions can span multiple databases;

  • Java transaction types are divided into JDBC transactions and JTA transactions

    • JDBC transaction: It is the local transaction in the database transaction mentioned above, controlled and managed through the connection object.

    • JTA transaction: JTA refers to Java Transaction API (Java Transaction API), which is the Java EE database transaction specification. JTA only provides a transaction management interface, which is controlled by the application Server vendors (such as WebSphere Application Server) provide implementations. JTA transactions are more powerful than JDBC and supports distributed transactions.

  • According to whether it is programmed, it is divided into declarative transactions and programmatic transactions. Please refer to http://blog.csdn.net/liaohaojian/article/details/70139151

    • Declarative transactions: implemented through XML configuration or annotations.

    • Programmatic transactions: Implemented through programming code when business logic is needed, with smaller granularity.

    3. Spring transaction isolation level: spring has five isolation levels, which are defined in the TransactionDefinition interface. Looking at the source code, we can see that its default isolation_default (the default level of the underlying database), and the other four isolation levels are consistent with the database isolation level.

    1. ISOLATION_DEFAULT: Use the default isolation level of the underlying database, whatever the database administrator sets

    2. ISOLATION_READ_UNCOMMITTED (uncommitted read): The lowest isolation level, the transaction can be read by other transactions before it is submitted (phantom reads, dirty reads, and non-repeatable reads will occur)

    3. ISOLATION_READ_COMMITTED (read committed) : A transaction can only be read by other transactions after it is submitted (this isolation level prohibits other transactions from reading the data of uncommitted transactions, so It will still cause phantom reading and non-repeatable reading), sql server default level

    4. ISOLATION_REPEATABLE_READ (repeatable reading) : repeatable reading, ensuring that multiple reads are performed at the same time When a piece of data is generated, its value is consistent with the content at the beginning of the transaction, and it is prohibited to read uncommitted data from other transactions (this isolation can basically prevent dirty reads and non-repeatable reads (the focus is on modification), but phantom reads will occur) (Focus on adding and deleting)) (MySql default level, changes can be made through set transaction isolation level level)

    5. ISOLATION_SERIALIZABLE (Serialization): The most expensive and most reliable isolation level (this isolation level can prevent dirty reads, non-repeatable reads, and phantom reads)

      1. Lost update: Two transactions update a row of data at the same time. The update of the last transaction will overwrite the update of the first transaction, resulting in the loss of the data updated by the first transaction. This It is caused by no locking;

      2. Phantom reading: During the same transaction operation, the same data is read multiple times (different transactions) in different time periods, and the read content is inconsistent. (Generally, the number of lines becomes more or less).

      3. Dirty read: A transaction reads the content of another transaction that is not mentioned, which is a dirty read.

      4. Non-repeatable reading: In the same transaction, the content read multiple times is inconsistent (generally the number of rows remains unchanged, but the content changes).

    The difference between phantom reading and non-repeatable reading: The focus of phantom reading is insertion and deletion, that is, the second query will find that the data is better than the first The query data becomes less or more, giving people an illusion. The key point of non-repeatable reading is modification, that is, the second query will find that the query results are inconsistent with the first query results, that is, The first time results are no longer reproducible.

    The higher the database isolation level, the higher the execution cost and the worse the concurrent execution capability. Therefore, comprehensive considerations must be taken when developing and using actual projects. In order to consider concurrency performancegenerally use submit Read isolation level, it can avoid lost updates and dirty reads. Although non-repeatable reads and phantom reads cannot be avoided, pessimistic locks or optimistic locks can be used to solve these problems when possible.

    4. Communication behavior: There are seven major communication behaviors, which are also defined in the TransactionDefinition interface.

    1. PROPAGATION_REQUIRED: Supports the current transaction. If there is no current transaction, create a new one.

    2. PROPAGATION_SUPPORTS: Supports the current transaction. If there is no transaction currently, it will be executed non-transactionally (there is a note in the source code, which is not clear, so leave it for later) will be studied later).

    3. PROPAGATION_MANDATORY: Supports the current transaction. If there is no current transaction, an exception will be thrown (it must be executed in an existing transaction. The business Methods cannot initiate their own transactions on their own).

    4. PROPAGATION_REQUIRES_NEW: Always create a new transaction. If there is currently a transaction, the original transaction will be suspended.

    5. PROPAGATION_NOT_SUPPORTED: The current transaction is not supported and is always executed in a non-transactional manner. If the current transaction exists, the transaction is suspended.

    6. PROPAGATION_NEVER: The current transaction is not supported; if the current transaction exists, an exception is thrown.

    7. PROPAGATION_NESTED: If the current transaction exists, it is executed in a nested transaction. If there is no current transaction, it performs an operation similar to PROPAGATION_REQUIRED (note : When applied to JDBC, only applicable to JDBC 3.0 or above driver).

    5.Spring transaction support

    1.spring provides many built-in transaction managers that support Different data sources. There are three common categories

    • DataSourceTransactionManager: Under the org.springframework.jdbc.datasource package, the data source transaction management class, Provides transaction management for a single javax.sql.DataSource data source, as long as it is used for JDBC and Mybatis framework transaction management.

    • HibernateTransactionManager: Under the org.springframework.orm.hibernate3 package, the data source transaction management class provides support for a single org.hibernate.SessionFactory transaction for integration. Transaction management in Hibernate framework; Note: This transaction manager only supports Hibernate3 version, and Spring3.0 version only supports Hibernate 3.2 version;

    • JtaTransactionManager: Located in the org.springframework.transaction.jta package, it provides support for distributed transaction management, and delegates transaction management to the Java EE application server, or customizes a local JTA transaction manager, nested into the application.

    The built-in transaction managers all inherit the abstract class AbstractPlatformTransactionManager, and AbstractPlatformTransactionManager inherits the interface PlatformTransactionManager

    The core of the Spring framework's support for transaction management is the transaction manager Abstract: For different data access frameworks, the strategy interface PlatformTransactionManager is implemented to support transaction management of multiple data access frameworks.

    PlatformTransactionManager interface is defined as follows

    The TransactionStatus interface is defined as follows:
    public interface TransactionStatus extends SavepointManager {  
           boolean isNewTransaction();  //返回当前事务是否是新的事务
           boolean hasSavepoint();  //返回当前事务是否有保存点
           void setRollbackOnly();  //设置事务回滚
           boolean isRollbackOnly();  //设置当前事务是否应该回滚
           void flush();  //用于刷新底层会话中的修改到数据库,一般用于刷新如Hibernate/JPA的会话,可能对如JDBC类型的事务无任何影响;
           boolean isCompleted();  //返回事务是否完成
    }

    2. Spring distributed transaction configuration

    • References the JNDI data source of the application server (such as Tomcat) to indirectly implement JTA transactions Management relies on the application server

    • to directly integrate JOTM (official website: http://jotm.objectweb.org/) and Atomikos (official website: https://www.atomikos.com/ ) Provides JTA transaction management (no application server support, often used for unit testing)

    • Use application server-specific transaction managers to use the advanced features of JTA transactions (Weblogic, Websphere)

    1). Reference the JNDI data source of the application server (such as Tomcat) to indirectly implement JTA transaction management. The configuration is as follows

    <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) Use Atomikos to implement distributed transaction management , the configuration is as follows:

    <?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>

    The above is the detailed content of Spring transaction isolation level, propagation behavior and spring+mybatis+atomikos realize distributed transaction management. For more information, please follow other related articles on the PHP Chinese website!

    Statement:
    The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn