事务简介及隔离

事务经常遇到的问题:

1.脏读 Dirty reads :事务A未提交之前(还在缓存中)修改了记录1,事务B读取记录1,如果事务A回滚,则事务B所读是错误数据。

2.不可重复读 non-repeatable reads:事务A中两处读取记录1中的值。第一次读取记录1值为“123”,事务B把记录1值修改为“456”,事务A第二次读结果变为“456”,数据混乱

3.幻想读 phantom reads:事务A中两处搜索字段a=1的所有记录。第一次搜索记录数1条,事务B增加了一条a=1的记录,事务A第二次搜索记录数2条,插入造成数据混乱

解决方式

设置事务的隔离级别isolation

ISOLATION_READ_UNCOMMITTED :最低隔离级别,允许一个事务看到另一个事务未提交的数据

ISOLATION_READ_COMMITTED:一个事务不能看到另一个事务未提交的数据,只能解决脏读,不能解决 不可重复都和幻想读

ISOLATION_REPEATABLE_READ:可防止脏读和不可重复读,但是不能解决 幻想读

ISOLATION_SERIALIZABLE:事务处理为顺序执行。代价最大,最安全。可解决脏读,不可重复都,幻想读

x锁 排他锁 被加锁的对象只能被只有锁的事务读取和修改,其他事务无法在该对象上加其他锁,也不能读取和修改对象

s锁 共享锁 被加锁的对象可以被持有锁事务读取,但是不能被修改,其他事务也可以在上面加共享锁不能加排他锁

共享锁下其他用户可以并发读取,查询数据。但不能修改增加,删除数据。

并发控制下乐观锁和悲观锁

悲观锁:假定会发生并发冲突,屏蔽一切可能违反数据完整性的操作

应用:实用数据库锁机制(排他锁)

乐观锁:假设不会发生并发冲突,只在提交操作时检查是否违法数据完整性

应用:1.使用自增长的整数表示数据版本号。每次提交+1,匹配相等可更新

    2.实用时间戳实现

spring配置事务实例:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns="http://www.springframework.org/schema/beans" 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:util="http://www.springframework.org/schema/util"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
						http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
						http://www.springframework.org/schema/aop
						http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
						http://www.springframework.org/schema/tx
						http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
			            http://www.springframework.org/schema/util
			            http://www.springframework.org/schema/util/spring-util-3.2.xsd						
						http://www.springframework.org/schema/context
						http://www.springframework.org/schema/context/spring-context-3.2.xsd">

	<!-- 开启注解配置 -->
	<context:annotation-config />
	<!-- 开启事务注解驱动 -->
	<tx:annotation-driven />
	<bean id="mybatisDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
		destroy-method="close">
		<property name="driverClass" value="${db_driver}" />
		<property name="jdbcUrl" value="${db_url}" />
		<property name="user" value="${db_username}" />
		<property name="password" value="${db_password}" />
		<!-- 最大空闲时间,超过空闲时间的连接将被丢弃。为0或负数则永不丢弃。默认为0 -->
		<property name="maxIdleTime" value="60" />
		<!-- 连接池中保留的最小连接数。 -->
		<property name="minPoolSize" value="1" />
		<!-- 连接池中保留的最大连接数。默认为15 -->
		<property name="maxPoolSize" value="5" />
		<!-- 隔多少秒检查所有连接池中的空闲连接,默认为0表示不检查 -->
		<property name="idleConnectionTestPeriod" value="60" />
		<!-- 初始化时创建的连接数,应在minPoolSize与maxPoolSize之间取值。默认为3 -->
		<property name="initialPoolSize" value="10" />
		<!-- 当连接池中的连接用完时,C3P0一次性创建新连接的数目 -->
		<property name="acquireIncrement" value="5" />
		<!-- 定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 -->
		<property name="acquireRetryAttempts" value="30" />
		<property name="acquireRetryDelay" value="100" />
		<!-- 获取连接失败将会引起所有等待获取连接的线程抛出异常。 但是数据源仍有效保留,并在下次调 用getConnection()的时候继续尝试获取连接。 
			如果设为true,那么在尝试获取连接失败后该数据源将申明已断开并永久关闭。默认为 false -->
		<property name="breakAfterAcquireFailure" value="true" />
	</bean>

	<!-- myBatis文件 -->
	<bean id="mybatisSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="configLocation" value="classpath:mybatis-config.xml" />
		<property name="dataSource" ref="mybatisDataSource" />
		<!-- 自动扫描entity目录, 省掉Configuration.xml里的手工配置 -->
		<property name="mapperLocations" value="classpath*:com/trustsaving/**/mapper/impl/*.xml" />
	</bean>


	<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
		<property name="basePackage" value="com.trustsaving.*.mapper" />
		<property name="sqlSessionFactoryBeanName" value="mybatisSessionFactory" />
	</bean>

	<!-- 配置事务管理器 -->
	<bean id="mybatisTransactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
		<property name="dataSource" ref="mybatisDataSource" />
		<property name="globalRollbackOnParticipationFailure" value="false" />
	</bean>

	<!-- 配置事务的传播特性 -->
	<tx:advice id="mybatisAdvice" transaction-manager="mybatisTransactionManager">
		<tx:attributes>
			<tx:method name="add*" propagation="REQUIRED" isolation="REPEATABLE_READ" rollback-for="Exception,RuntimeException" />
			<tx:method name="create*" propagation="REQUIRED" isolation="REPEATABLE_READ"  rollback-for="Exception,RuntimeException" />
			<tx:method name="save*" propagation="REQUIRED" isolation="REPEATABLE_READ"  rollback-for="Exception,RuntimeException" />
			<tx:method name="edit*" propagation="REQUIRED" isolation="REPEATABLE_READ"  rollback-for="Exception,RuntimeException" />
			<tx:method name="update*" propagation="REQUIRED" isolation="REPEATABLE_READ"  rollback-for="Exception,RuntimeException" />
			<tx:method name="modify*" propagation="REQUIRED" isolation="REPEATABLE_READ"  rollback-for="Exception,RuntimeException" />
			<tx:method name="get*" propagation="REQUIRED" isolation="REPEATABLE_READ"  rollback-for="Exception,RuntimeException" />
			<tx:method name="find*" propagation="SUPPORTS" isolation="REPEATABLE_READ"  rollback-for="Exception,RuntimeException" />
			<tx:method name="query*" propagation="SUPPORTS" isolation="REPEATABLE_READ"  rollback-for="Exception,RuntimeException" />
			<tx:method name="join*" propagation="SUPPORTS" isolation="REPEATABLE_READ"  rollback-for="Exception,RuntimeException" />
			<tx:method name="buy*" propagation="REQUIRED" isolation="REPEATABLE_READ"  rollback-for="Exception,RuntimeException" />
			<tx:method name="end*" propagation="REQUIRED" isolation="REPEATABLE_READ"  rollback-for="Exception,RuntimeException" />
			<tx:method name="run*" propagation="REQUIRED" isolation="REPEATABLE_READ"  rollback-for="Exception,RuntimeException" />
			<tx:method name="clearing*" propagation="REQUIRED" isolation="REPEATABLE_READ"  rollback-for="Exception,RuntimeException" />
			<tx:method name="liquidation*" propagation="REQUIRES_NEW" isolation="REPEATABLE_READ"  rollback-for="Exception,RuntimeException" />
			<tx:method name="*" read-only="true" />
		</tx:attributes>
	</tx:advice>

	<!--哪些类的哪些方法参与事务 -->
	<aop:config>
		<aop:pointcut id="mybatisServiceOperation" expression="execution(* com.trustsaving.MatchMoudle.service..*ServiceImpl.*(..))" />
		<aop:advisor advice-ref="mybatisAdvice" pointcut-ref="mybatisServiceOperation" />
	</aop:config>
</beans>

事务传播性propagation

PROPAGATION_REQUIRED:支持当前事务,如果当前没有事务则新建一个事务。这是最常见选择

PROPAGATION_SUPPORTS:支持当前事务,如果当前没有事务则按照无事务方式执行

PROPAGATION_MANDATORY:支持当前事务,如果没有事务则抛出异常

PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,则当前事务挂起

PROPAGATION_NOT_SUPPORTED:以非事务方式执行,如果当前存在事务,则把当前事务挂起

PROPAGATION_NEVER:已非事务方式执行,如果当前存在事务,则抛出异常

PROPAGATION_NESTED:

理解Nested的关键是savepoint。他与PROPAGATION_REQUIRES_NEW的区别是,PROPAGATION_REQUIRES_NEW另起一个事务,将会与他的父事务相互独立,

而Nested的事务和他的父事务是相依的,他的提交是要等和他的父事务一块提交的。也就是说,如果父事务最后回滚,他也要回滚的。

而Nested事务的好处是他有一个savepoint。

*****************************************

ServiceA {

/**

* 事务属性配置为 PROPAGATION_REQUIRED

*/

void methodA() {

try {

//savepoint

ServiceB.methodB(); //PROPAGATION_NESTED 级别

} catch (SomeException) {

// 执行其他业务, 如 ServiceC.methodC();

}

}

}

********************************************

也就是说ServiceB.methodB失败回滚,那么ServiceA.methodA也会回滚到savepoint点上,ServiceA.methodA可以选择另外一个分支,比如

ServiceC.methodC,继续执行,来尝试完成自己的事务。

但是这个事务并没有在EJB标准中定义

引用自:http://blog.csdn.net/it_man/article/details/5074371


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值