一文看懂spring事务原理

1、摘记

事务的作用
事务操作包含两个目的,数据一致以及操作隔离。

  • 数据一致是指事务提交时保证事务内的所有操作都成功完成,并且更改永久生效;事务回滚时,保证能够恢复到事务执行之前的状态。
  • 操作隔离则是指多个同时执行的事务之间应该相互独立,互不影响。

隔离级别

MySQL的InnoDB引擎提供四种隔离级别(即ACID中的I):

  • 读未提交(READ UNCOMMITTED)
  • 读已提交(READ COMMITTED)
  • 可重复读(REPEATABLE READ)
  • 串行化(SERIALIZABLE)

InnoDB默认的隔离级别是REPEATABLE READ,其可避免脏读和不可重复读,但不能避免幻读,需要指出的是,InnoDB引擎的多版本并发控制机制(MVCC)并没有完全避免幻读

传播机制

当一个方法开启事务后,在方法中调用了其他的方法,其他方法可能也需要事务管理,此时就涉及事务该如何传播了。

  • TransactionDefinition.PROPAGATION_REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。
  • TransactionDefinition.PROPAGATION_REQUIRES_NEW:新建事务,如果当前存在事务,则把当前事务挂起,这个方法会独立提交事务,不受调用者的事务影响,父级异常,它也是正常提交
  • TransactionDefinition.PROPAGATION_SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
  • TransactionDefinition.PROPAGATION_NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
  • TransactionDefinition.PROPAGATION_NEVER:以非事务方式运行,如果当前存在事务,则抛出异常,即父级方法必须无事务。
  • TransactionDefinition.PROPAGATION_MANDATORY:如果当前存在事务,则加入该事务;如果当前无事务,则抛出异常,也即父级方法必须有事务
  • TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,它将会成为父级事务的一个子事务,方法结束后并没有提交,只有等父事务结束才提交。如果当前没有事务,则新建事务。如果它异常,父级可以捕获它的异常而不进行回滚,正常提交。但如果父级异常,它必然回滚,这就是和 REQUIRES_NEW 的区别。

保存点

事务中可以设置一些保存点(阶段标识),回滚时可以指定回滚到前面的哪个保存点。

2、事务操作

既然有事务,就少不了有事务管理者,不然用户在进行事务相关操作的时候还需要自己去处理事务,显然不合理。而一个事务管理者应该具有哪些功能呢?通过spring中的源码我们可以知道只有两个主要功能

  • 提交
  • 回滚
    在这里插入图片描述
2.1、获取事务

我们要对事务进行操作,首先就是需要获取到对应的事务(也可以认为是何时创建事务)

前置知识点:事务的传播机制(具体查看摘记中对于事务传播机制的介绍)

我们在获取事务时,首先需要判断一下调用者是否已经是一个事务,例如调用者A和被调用者B,A和B同时开启事务,在A调用B时,就知道当前调用者已经有事务了。这时B的事务性如何需要根据事务的传播机制来判断,流程如下,如果A没有事务,那么B就简单多了,直接创建一个事务即可
在这里插入图片描述

2.2、提交

因为事务能够保证事务内的所有操作都成功完成,那么我们就应该在所有操作完成后告诉事务管理者,这个事务中的所有操作都好了,此时事务管理者就会进行提交操作。

这里就引出了事务管理者的第一个功能–提交。

在这里插入图片描述

在spring中事务管理者顶级抽象接口是TransactionManager,标识这是一个事务管理者,其中没有定义任何的函数。TransactionManager的实现接口是PlatformTransactionManager,这个上定义了

void commit(TransactionStatus status) throws TransactionException;

AbstractPlatformTransactionManager是定义在spring tx框架上通用的事务管理者,其中提供了很多钩子函数,在其他的框架里中可以自定义其实现类来定义特定的事务管理者。
目前实现的有org.springframework.jdbc.datasource中的DataSourceTransactionManager,这个事务管理者可以工作在JDBC 驱动程序中

窥探spring AbstractPlatformTransactionManager中的commit函数

前置知识点
在这里插入图片描述
TransactionStatus:事务状态,其实现了TransactionExecutionSavepointManager接口。

其中TransactionExecution保存的状态值有

  • isNewTransaction 是否是新事务
  • isRollbackOnly 是否仅能回滚
  • isCompleted 是否已完结

SavepointManager是保存点管理者,可以用来创建保存点,将当前事务回滚到保存点,释放保存点

所以我们在调用commit方法时需要传入TransactionStatus对象,这个对象上保存着当前事务的状态。

进攻源码
在这里插入图片描述
接下来进入到processCommit方法中
在这里插入图片描述
在这里插入图片描述
这边回调下文再分析,主要是doCommit函数,但是这个commit的具体操作函数也是一个钩子函数,需要具体用的地方去进行具体实现,毕竟这里只是通用的函数。大家可以推测出在这个类的所有do字打头的具体工作函数都是需要此类的子类来实现的。

DataSourceTransactionManager中的实现
在这里插入图片描述
可以看到spring实际上就是对于底层所有的事务操作就是提供了兼容性,这里具体的提交操作还是需要调用具体的服务来实现。

2.3、回滚

整体上回滚的操作和提交类似
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
而具体的回滚操作也是需要具体的子类去进行实现

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值