大家都知道,Spring的声明式事务是通过事务属性来定义的,而spring的事务属性包含了5个方面:传播行为,隔离级别,是否只读,事务超时,回滚规则;

传播行为

  传播行为,是属于事务边界相关的属性,定义了何时要创建一个事务或何时使用已有的事务。

Spring提供了7种不同的传播行为:

PROPAGATION_REQUIRED 该方法必须在事务中运行,如果当前事务不存在,则启动一个新的事务,如果当前事务存在,就在这个事务中执行,是最常见的;
PROPAGATION_MANDATORY 该方法必须在事务中进行,如果没有事务,则抛出一个异常;
PROPAGATION_NESTED 如果当前存在事务,那么该方法将会在嵌套事务内运行,嵌套事务可以独立于当前事务进行单独的提交或回滚。如果当前没有事务,则进行与PROPAGATION_REQUIRED相同的操作;
PROPAGATION_SUPPORTS 表示该方法不需要必须在事务中运行,如果当前存在事务,则运行在该事务中,如果不存在,则按非事务方式运行;
PROPAGATION_REQUIRES_NEW 表示方法必须运行在它自己的事务中。如果当前存在事务,则该事务会被挂起,会启动一个新的事务来执行方法;
PROPAGATION_NOT_SUPPORTED 表示该方法不应该运行在事务中,如果当前存在事务,则在方法运行期间,该事务会被挂起;
PROPAGATION_NEVER 表示该方法不应该运行在事务中,如果当前存在事务,则会抛出一个异常;

  如果声明了方法的传播行为为PROPAGATION_REQUIRES_NEW ,这就意味着事务边界与方法自己的边界是一样的:方法在开始执行的时候启动一个新事务并在方法返回或抛出异常时结束该事务。

隔离级别

隔离级别决定了一个事务会被其他并行的事务所能影响的程度

1. 为什么要有事务隔离级别以及能解决的问题 (why)?

  在一个多用户,用并发的系统中,为了保证数据的一致性和完整性,避免出现脏读、不可重复读、幻读等情况,引入了事务隔离机制的概念;

2. 脏读、不可重复读、幻读概念?

  脏读:一个事务读取到另一事务未提交的更新新据。当一个事务正在访问数据,并且对数据进行了修改,而这种修改还没有提交到数据库中,这时,另外一个事务也访问这个数据,然后使用了这个数据。因为这个数据是还没有提交的数据, 那么另外一个事务读到的这个数据是脏数据,依据脏数据所做的操作也可能是不正确的;

  不可重复读:在同一事务中,多次读取同一数据返回的结果有所不同。换句话说就是,后续读取可以读到另一事务已提交的更新数据。相反,“可重复读”在同一事务中多次读取数据时,能够保证所读数据一样,也就是,后续读取不能读到另一事务已提交的更新数据。

  幻读:和不可重复读类似,但不同的是不可重复读的是update,幻读的是insert。事务T1执行一次查询,然后事务T2新插入一行记录,这行记录恰好可以满足T1所使用的查询的条件。然后T1又使用相同的查询再次对表进行检索,但是此时却看到了事务T2刚才插入的新行。这个新行就称为“幻像”,因为对T1来说这一行就像突然出现的一样。

3. 事务隔离级别?

  一般来说,分为四个隔离级别:

  a. 未提交读(Read uncommitted):读未提交数据,这是事务最低的隔离级别,在并发的事务中,它充许一个事务可以读到另一个事务未提交的更新数据(会出现脏读,不可重复读和幻读);

  b. 已提交读(Read committed):读已提交数据,保证在并发的事务中,一个事务修改的数据提交后才能被另外一个事务读取到(会出现不可重复读和幻读);

  c. 可重复读(Repeatable read):可重复读,这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻读。一般是采用“快照”的方式来实现的;

  d. 可串行化(Serializable ):事务被处理为顺序执行或者说是以串行化方式执行。这是花费最高,但也是最可靠的事务隔离级别。能有效的避免脏读、不可重复读、幻读。

4. 数据库默认的隔离级别?

  每种数据库的默认隔离级别是不同的,例如SQL Server、Oracle默认Read Commited,MySQL默认Repeatable Read。

参考自:https://gist.github.com/JagoWang/4555317#file-mysql-L27

https://tech.meituan.com/innodb-lock.html

是否只读

  如果事务只对后端的数据库进行读操作,数据库可以利用事务的只读特性来进行一些优化;通过将事务设置为只读,你就可以给数据库一个机会,让它应用它认为何时的优化措施,例如Oracle对于只读事务,不启动回滚段,不记录回滚log;

  如果你一次执行多条查询语句,例如统计查询,报表查询,在这种场景下,多条查询SQL必须保证整体的读一致性,否则,在第一条SQL查询之后,第二条SQL查询之前,数据被其他用户改变,则该次整体的统计查询将会出现读数据不一致的状态,此时,应该启用事务支持。
【注意是一次执行多次查询来统计某些信息,这时为了保证数据整体的一致性,要用只读事务】

  没有事务的时候,在执行一条sql语句看到执行前点的数据状态,保证数据一致性;

  只读事务,在执行多条sql语句看到执行前点的数据状态,保证数据一致性;

事务超时

  为了使应用程序更好的运行,事务不能运行太长的时间。因为事务可能涉及对后端数据库的锁定,所以长时间的事务会不必要的占用数据库资源。

回滚规则

  默认情况下,事务只有在遇到运行期异常时才会回滚(java.lang.RuntimeException及其子类),而在遇到检查型异常时不会回滚;不过,我们可以手动设置回滚时的异常类型;

我们可以使用@Transaction注解中的noRollbackFor和RollbackFor指定某种异常是否回滚。

@Transaction(noRollbackFor=RuntimeException.class)
@Transaction(RollbackFor=Exception.class)
这样就改变了默认的事务处理方式。  

  这就要求我们在自定义异常的时候,让自定义的异常继承自RuntimeException,这样抛出的时候才会被Spring默认的事务处理准确处理。

参考自《Spring实战》

【Spring事务的事务属性】的更多相关文章

  1. Spring 声明式事务,propagation属性列表及isolation(隔离级别)

    Spring 声明式事务,propagation属性列表 TransactionDefinition接口中定义,共有7种选项可用: PROPAGATION_REQUIRED:支持当前事务,如果当前没有 ...

  2. FlushMode属性与transaction(spring注入的事务)

    一.参见hibernate的api http://tool.oschina.net/apidocs/apidoc?api=hibernate-3.6.10 http://tool.oschina.ne ...

  3. Spring事务配置的五种方式和spring里面事务的传播属性和事务隔离级别

    转: http://blog.csdn.net/it_man/article/details/5074371 Spring事务配置的五种方式 前段时间对Spring的事务配置做了比较深入的研究,在此之 ...

  4. [Spring] Spirng中的AOP进行事务的传播属性和事务隔离级别

    通知注解 前置通知(@Before):在某连接点(join point)之前执行的通知,但这个通知不能阻止连接点前的执行(除非它抛出一个异常) 返回后通知(@AfterReturning):在某连接点 ...

  5. 关于Spring 事务管理传播属性的配置及作用-嵌套事务

    先了解事务的7种传播属性: PROPAGATION_REQUIRED -- 支持当前事务,如果当前没有事务,就新建一个事务.这是最常见的选择. PROPAGATION_SUPPORTS -- 支持当前 ...

  6. 使用spring声明式事务,spring使用AOP来支持声明式事务,会根据事务属性,自动在方法调用之前决定是否开启一个事务,并在方法执行之后决定事务提交或回滚事务。

    使用spring声明式事务,spring使用AOP来支持声明式事务,会根据事务属性,自动在方法调用之前决定是否开启一个事务,并在方法执行之后决定事务提交或回滚事务.

  7. 事务的传播属性及隔离级别 Spring

    事务的传播属性(Propagation) REQUIRED ,这个是默认的属性 Support a current transaction, create a new one if none exis ...

  8. spring声明式事务管理总结

    事务配置 首先在/WEB-INF/applicationContext.xml添加以下内容: <!-- 配置事务管理器 --> <bean id="transactionM ...

  9. Spring声明式事务管理基于@Transactional注解

    概述:我们已知道Spring声明式事务管理有两种常用的方式,一种是基于tx/aop命名空间的xml配置文件,另一种则是基于@Transactional 注解.         第一种方式我已在上文为大 ...

  10. Spring学习8-Spring事务管理(注解式声明事务管理)

    步骤一.在spring配置文件中引入<tx:>命名空间 <beans xmlns="http://www.springframework.org/schema/beans& ...

随机推荐

  1. [洛谷P3793]由乃救爷爷

    题目大意:有$n(n\leqslant2\times10^7)$个数,$m(m\leqslant2\times10^7)$个询问,每次询问问区间$[l,r]$中的最大值.保证数据随机 题解:分块,处理 ...

  2. 【贪心】【UVA10905】 Children's Game

    传送门 Description 给定n个正整数,求他们相连接后能形成的最大整数.例如:12,23这两个数能连接的最大数是2312,. Input 多组数据,每组数据中: 第一行为一个整数n 第二行有n ...

  3. 直通BAT面试算法精讲课 --动态规划

    1.有数组penny,penny中所有的值都为正数且不重复.每个值代表一种面值的货币,每种面值的货币可以使用任意张,再给定一个整数aim(小于等于1000)代表要找的钱数,求换钱有多少种方法. 给定数 ...

  4. Android滚动栏控件的优化

    背景 由于普通TextView的跑马灯效果与焦点获取有关 所以不能直接使用 之前查找到的控件在数据设置方面存在问题 所以通过寻找github上的开源控件 并修改源码 得到一个目前感觉不错的效果 原理  ...

  5. javascript实现购物车思路

    /* 思路: 第一步:获取所要操作的节点对象 第二步:当页面加载完后,需要计算本地cookie存了多少[个]商品,把个数赋值给count 第三步:为每一个商品对应的添加购物车按钮绑定一个点击事件onc ...

  6. 整数中1出现的次数(从1到n整数中1出现的次数)

    整数中1出现的次数(从1到n整数中1出现的次数) 题目描述 求出1 ~ 13的整数中1出现的次数,并算出100 ~ 1300的整数中1出现的次数?为此他特别数了一下1 ~ 13中包含1的数字有1.10 ...

  7. 上下文路径request.getContextPath();与${pageContext.request.contextPath}

    (1) request.getContextPath();与${pageContext.request.contextPath}都是获取上下文路径: 1. request.getContextPath ...

  8. 51Nod 1004 n^n末尾数字 | 快速幂

    #include "bits/stdc++.h" using namespace std; #define LL long long #define INF 0x3f3f3f3f3 ...

  9. HDU 1070 Milk (模拟)

    题目链接 Problem Description Ignatius drinks milk everyday, now he is in the supermarket and he wants to ...

  10. bzoj 1968 数学

    在1-n所有数中,i一共可以成为n/i个数的约数,也即所有的约数中有n/i个i,所以扫一遍累加答案就好了. /********************************************* ...