Spring事务知识

Posted by 大雁小鱼的博客 on June 20, 2018

Spring事务隔离级别和传播特性

相信不少同学都在面试的时候被闻到过事务的隔离级别和传播特性吧,下面我就来聊一聊这个话题

传播特性

传播特性回答了当前方法是应该新建一个事务,还是当前事务被挂起,还是在当前事务下运行的规则说明,具体的来说,spring定义了7种传播特性

参数 传播意义(网上的说法) 我的理解
PROPAGATION_REQUIRES 表示当前方法必须在一个事务中运行。如果一个现有事务正在进行中,该方法将在那个事务中运行,否则就要开始一个新事务 如果当前有事务存在,则方法在这个事务中运行,否则就新建一个
PROPAGATION_REQUIRES_NEW 表示当前方法必须在它自己的事务里运行。一个新的事务将被启动,而且如果有一个现有事务在运行的话,则将在这个方法运行期间被挂起 总是新开一个事务
PROPAGATION_NOT_SUPPORTED 表示该方法不应该在一个事务中运行。如果一个现有事务正在进行中,它将在该方法的运行期间被挂起 该方法不在事务之内
PROPAGATION_NEVER 表示当前的方法不应该在一个事务中运行。如果一个事务正在进行,则会抛出一个异常 当前方法不能写在事务里面
PROPAGATION_NESTED 表示如果当前正有一个事务在进行中,则该方法应当运行在一个嵌套式事务中。被嵌套的事务可以独立于封装事务进行提交或回滚。如果封装事务不存在,行为就像PROPAGATION_REQUIRES一样
PROPAGATION_MANDATORY 表示该方法必须运行在一个事务中。如果当前没有事务正在发生,将抛出一个异常
PROPAGATION_SUPPORTS 表示当前方法不需要事务性上下文,但是如果有一个事务已经在运行的话,它也可以在这个事务里运行

这里我写了一个应用程序,逻辑是转账,现转进,再转出,代码如下

在代码中,由于里层的转进代码使用了PROPAGATION_REQUIRES_NEW传播特性,导致数据只进不出,钱多出来了。

隔离级别

隔离级别说的是两个事务互相影响的程度,因为在高并发两个事务操作同一份数据的可能性很大,所以一定存在一些问题的。

  • 脏读 脏读就是一个事务读取了另一个事务改写的但还尚未提交的数据
  • 不可重复读 一个事务读到了另一个事务改写之前和改写之后的数据,导致数据不一致
  • 幻读 (我还不太理解)

在理想状态下,事务之间将完全隔离,从而可以防止这些问题发生。然而,完全隔离会影响性能,因为隔离经常牵扯到锁定在数据库中的记录(而且有时是锁定完整的数据表)。侵占性的锁定会阻碍并发,要求事务相互等待来完成工作。
完全隔离会影响性能,而且并不是所有应用程序都要求完全隔离,所以有时可以在事务隔离方面灵活处理。因此,就会有好几个隔离级别。

参数 含义
ISOLATION_DEFAULT 使用后端数据库默认的隔离级别
ISOLATION_READ_UNCOMMITTED 允许读取尚未提交的更改
ISOLATION_READ_COMMITTED 允许从已经提交的事务读取
ISOLATION_REPEATABLE_READ 对相同字段的多次读取的结果是一致的
ISOLATION_SERIALIZABLE 完全的串行化,避免所有问题

mysql默认值是 ISOLATION_REPEATABLE_READ
Oracle默认值是 ISOLATION_READ_COMMITTED

参考网址

https://www.cnblogs.com/zhishan/p/3195219.html
https://blog.csdn.net/weixin_38070406/article/details/78157603