博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
spring事务
阅读量:6992 次
发布时间:2019-06-27

本文共 4164 字,大约阅读时间需要 13 分钟。

hot3.png

事务定义

    事务,就是一组操作数据库的动作集合。如果一组处理步骤或者全部发生或者一步也不执行,我们称该组处理步骤为一个事务。当所有的步骤像一个操作一样被完整地执行,我们称该事务被提交。由于其中的一部分或多步执行失败,导致没有步骤被提交,则事务必须回滚到最初的系统状态。

事务特点(ACID)

1.原子性:一个事务中所有对数据库的操作是一个不可分割的操作序列,要么全做要么全不做

2.一致性:事务执行前后过程中数据的完整性必须保持一致性

3.隔离性:多个用户并发访问数据库时,一个用户的事务的执行,不受其他用户事务的干扰,即并发执行的多个事务之间数据要相互隔离。

4.持久性:一个事物一旦提交,它对数据库的改变就是永久的。

 

事务管理器

    spring本身不管理事务,而是提供了多种事务管理器。它们将事务管理的工作委托给对应的持久化平台实现:

aca09a840c648eceb3f1934d46abe54c6c1.jpg

声明式事务

    spring中的声明式事务是通过事务属性去定义的。

    事务属性包含了5个方面:传播行为、隔离级别、回滚规则、事务超时、是否只读。

 

传播行为

    解决业务层方法之间的相互调用问题。

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

 PROPAGATION_SUPPORTS -- 支持当前事务,如果当前没有事务,就以非事务方式执行。
 PROPAGATION_MANDATORY -- 支持当前事务,如果当前没有事务,就抛出异常。
 PROPAGATION_REQUIRES_NEW -- 新建事务,如果当前存在事务,把当前事务挂起。
 PROPAGATION_NOT_SUPPORTED -- 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
 PROPAGATION_NEVER -- 以非事务方式执行,如果当前存在事务,则抛出异常。
 PROPAGATION_NESTED--如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,就新建一个事务。嵌套的事务可以独立于当前存在的事务进行单独的提交或回滚,也就是出现异常时,可以选择某一个事务单独提交还是回滚操作。

    例如:

    controller某个方法调用了service1的 test1方法 和 service2 的 test2方法 .如果test1 和 test2 方法都定义为 PROPAGATION_REQUIRED

    在test1执行时,由于是PROPAGATION_REQUIRED 当前事务不存在,新建了一个事务;在 test2 执行时,由于也是 PROPAGATION_REQUIRED,则进入到了test1创建的事务中。

    因此,若test2中出现了异常,则不仅test2所作的操作将回滚,test1的操作也将回滚。

 

隔离级别

    隔离级别是指若干个并发的事务之间的隔离程度。

  •     ISOLATION_DEFAULT--这是一个PlatfromTransactionManager默认的隔离级别:使用数据库默认的事务隔离级别(mysql默认为REPEATABLE_READoracle默认为READ_COMMITTED);
  •     ISOLATION_READ_UNCOMMITTED--这是事务最低的隔离级别,一个事务可以读取另一个事务读写但未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。
  •     ISOLATION_READ_COMMITTED--保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。
  •     ISOLATION_REPEATABLE_READ--这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免不可重复读。
  •     ISOLATION_SERIALIZABLE--这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。

1)幻读:事务1先读取1次记录,当事务2增加了某些记录并提交,此时事务1再次读取时发现第二次读取比第一次读取多了一些之前不存在的记录;

2)不可重复读取:事务1先读取一次记录,当事务2更新了某些记录并提交,此时事务1再次读取时发现两次读取结果不一致;
3)脏读:事务1更新了记录,但没有提交,事务2读取到了事务1更新之后的记录,当事务T1回滚,则事务T2读取的数据无效。

    隔离级别主要是为了解决并发情况下,数据的一致性问题。因此可以看作是多个线程同时访问一个方法:

  1.     ISOLATION_READ_UNCOMMITTED 就是什么都不做。 
  2.     ISOLATION_READ_COMMITTED 一旦某个事务对某条记录进行了修改,在提交事务之前都将持有该条记录的行锁,不允许其他事务读取和修改。(只有修改才加锁)
  3.     ISOLATION_REPEATABLE_READ 一旦某个事务对某条记录进行了修改,在提交事务之前都将持有该条记录的行锁,不允许其他事务读取和修改。 一旦某个事务对某条记录进行了读取,在提交事务之前也将持有该条记录的行锁,不允许其他事务读取和修改。(修改和读取都加锁
  4.     ISOLATION_SERIALIZABLE 规定事务的执行顺序,在前一个事务没有提交之前,下一个事务无法开始执行。

 

回滚规则

    定义当遇到哪些异常就要进行回滚操作。默认情况,事务只有遇到运行时异常 RunTimeException 才会回滚,而遇到受检型异常时(如IOException、SQLException),则不会回滚。

    spring允许自定义回滚规则。因此,在声明事务时,可以声明当事务遇到特定的检查型异常时同样也会回滚,同样也可以声明在遇到某些特定异常不回滚,哪怕那个异常属于 运行时异常。

 

事务超时

    定义一个事务执行的最大时间,可以防止某些事务长时间占用数据库资源,当事务运行超时,将自动回滚,而不是无限等待其运行结束为止。

    由于该超时时钟是在事务创建时才会启动,因此只有PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW 、PROPAGATION_NESTED 这3个能够在不存在事务时创建新事务的传播行为,考虑设置相应的事务超时时间,才是有意义的。

 

是否只读

    如果事务只对数据库进行读取操作,数据库可以利用事务只读特性对其进行相应优化。由于该优化是在事务创建时数据库去实施的,因此只有PROPAGATION_REQUIRED、PROPAGATION_REQUIRES_NEW 、PROPAGATION_NESTED 这3个能够在不存在事务时创建新事务的传播行为,考虑设置为只读,才是有意义的。

 

在XML定义事务

    tx 标签中相关属性:

  1.     isolation:隔离级别。    取值:DEFAULT、READ_UNCOMMITTED、READ_COMMITTED、REPEATABLE_READ、SERIALIZABLE
  2.     propagation:传播规则。    取值:REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、SUPPORTED、NEVER、NESTED
  3.     read-only:是否只读    取值:true、false
  4.     rollback-for:指定哪些异常回滚    eg:java.lang.Exception
  5.     no-rollback-for:指定哪些异常将继续运行而不回滚    eg:java.lang.Exception
  6.     timeout:事务超时时间(秒) 

 

使用注解定义事务

    在xml中,添加少量的配置:

    在需要事务管理的类上加 ,则表示该类的所有方法都拥有相同的事务属性;也可只在需要事务管理的方法上加@Transactional。 

    eg:

@Transactional(propagation = Propagation.NESTED,isolation = Isolation.DEFAULT,readOnly = true,rollbackFor={java.lang.Exception.class},noRollbackFor = {java.sql.SQLException.class},timeout = 10)public void test(){   //...}

     中相关属性:

  1.     isolation:隔离级别。    取值:Isolation.DEFAULT、Isolation.READ_UNCOMMITTED、Isolation.READ_COMMITTED、Isolation.REPEATABLE_READ、Isolation.SERIALIZABLE
  2.     propagation:传播规则。    取值:Propagation.REQUIRED、Propagation.SUPPORTS、Propagation.MANDATORY、Propagation.REQUIRES_NEW、Propagation.SUPPORTED、Propagation.NEVER、Propagation.NESTED
  3.     readOnly:是否只读    取值:true、false
  4.     rollbackFor:指定哪些异常回滚    eg:java.lang.Exception
  5.     noRollbackFor:指定哪些异常将继续运行而不回滚    eg:java.lang.Exception
  6.      timeout:事务超时时间(秒) 

 

转载于:https://my.oschina.net/langwanghuangshifu/blog/2246863

你可能感兴趣的文章
get与post在技术上的区别
查看>>
ios面试题(二)
查看>>
设置section的距离
查看>>
logback节点配置详解
查看>>
Create Extraction Zone
查看>>
MVC_里面的增、删、改、查
查看>>
vs2013 + python3.52 + boost1.61, 编译C++库失败
查看>>
[题解]第十一届北航程序设计竞赛预赛——F.序列
查看>>
KMP
查看>>
TCP IP 的AT命令
查看>>
iPhone用股票k线组件源码,支持其他图表类型
查看>>
桶排序问题——非对比排序
查看>>
转:Linux性能评测工具之一:gprof篇
查看>>
【图像处理Matlab】2 灰度变换 imadjust stretchlim
查看>>
top命令详解
查看>>
Webdriver其他定位方式
查看>>
解决手机日常使用太卡问题
查看>>
win8.1 chrome 开始屏幕 没有注册类 解决方案
查看>>
myeclipse工程 junit不能运行 ClassNotFoundException
查看>>
暴力 hihoCoder 1178 计数
查看>>