spring事务本质

目录
数据库事务
spring事务与数据库事务与锁之间的关系
MySQL事务隔离级别
编程式和声明式事务的区别
Spring声明式事务

本人虽然做了几年的java开发了,很早就接触到了spring,当然也接触到spring的事务,但是由于常年忙于业务实现,自己对spring事务这块也是比较模糊,说懂也懂些,但并不系统深入,趁着最近要对自己的知识体系进行梳理,我参考了一些博客和书籍,整理了一些结论性的东西。
数据库事务
数据库事务(简称:事务)是数据库管理系统执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
事务处理可以用来维护数据库的完整性,保证成批的 SQL 语句要么全部执行,要么全部不执行。
事务用来管理 insert,update,delete 语句
由于目前MySQL应用范围比较广泛,我们今天主要针对MySQL 数据库进行阐述。
在 MySQL 中只有使用了 Innodb 数据库引擎的数据库或表才支持事务。在 5.5.5*版本之前默认的引擎都是MyISAM 而该引擎是不支持事务的,InnoDB引擎是支持的,去检查表是什么引擎 用指令 show create table TABLENAME指令查看 这里的TABLENAME是自己的表名

spring事务与数据库事务与锁之间的关系
一直没搞清楚spring事务与数据库事务与锁之间的关系,也许是因为这个体系非常庞大,确实比较凌乱。
其实spring事务是基于数据库事务进行的实现,方便用户屏蔽数据库事务的具体实现,快速实现事务处理的。

      后来从一个博客上看到:**spring事务本质上使用数据库事务,而数据库事务本质上使用数据库锁,所以spring事务本质上使用数据库锁,开启spring事务意味着使用数据库锁,那么事务的隔离级别与锁有什么关系呢?本人认为事务的隔离级别是通过锁的机制实现的,事务的隔离级别是数据库开发商根据业务逻辑的实际需要定义的一组锁的使用策略**,这句话确实有一点的启示作用。
1
MySQL事务隔离级别
推荐博文:五分钟搞清楚MySQL事务隔离级别 
心得:事务隔离级别是针对当前会话所在事务设置隔离级别, 限制自己查询别的事务的数据级别

推荐博文:幻读和不可重复读的区别
心得:幻读和不可重复读都是读取了另一条已经提交的事务(这点和脏读不同),所不同的是不可重复读是在一个事物里查询同一条数据两次读的结果不一样,幻读是读到之前没有出现过的数据(新增或删除)

推荐博文:mysql Innodb在RR级别如何避免幻读 https://www.jianshu.com/p/2953c64761aa
心得:在快照读情况下,mysql通过mvcc来避免幻读。在当前读情况下,mysql通过next-key来避免幻读

推荐博文:MySQL高级锁机制 https://blog.csdn.net/why15732625998/article/details/80439315

推荐博文:spring事务管理(详解和实例) https://mp.csdn.net/postlist
心得:事务隔离级别是针对自己这个事务的,定义自己可以读取其他事务数据的级别,事务的传播特性是在别的方法调用时,自己这个方法如何开启事务。
不可重复读 :在一个事务中前后两次读取的结果并不一致,导致了不可重复读。
幻读的重点在于新增或者删除:
同样的条件, 第1次和第2次读出来的记录数不一样
从总的结果来看, 似乎不可重复读和幻读都表现为两次读取的结果不一致。但如果你从控制的角度来看, 两者的区别就比较大。
对于前者, 只需要锁住满足条件的记录。
对于后者, 要锁住满足条件及其相近的记录

编程式和声明式事务的区别
Spring提供了对编程式事务和声明式事务的支持,编程式事务允许用户在代码中精确定义事务的边界,而声明式事务(基于AOP)有助于用户将操作与事务规则进行解耦。
简单地说,编程式事务侵入到了业务代码里面,但是提供了更加详细的事务管理;而声明式事务由于基于AOP,所以既能起到事务管理的作用,又可以不影响业务代码的具体实现。

Spring声明式事务
初学java的程序员都知道用注解来声明事务,开启事务管理,但是想要正确的应用可不容易。 大家都知道spring事务是通过aop 动态代理模式开启事务的,也就是说首先调用的是AOP代理对象而不是目标对象,首先执行事务切面,事务切面内部通过TransactionInterceptor环绕增强进行事务的增强,即进入目标方法之前开启事务,退出目标方法时提交/回滚事务。大家只要记住一点,只有通过spring容器的代理对象调用的并且是有@Transactional 注解且公有的方法才会开启事务,其他情况一律不行 ,现实的应用中会出现一些事务失效的情况,那它肯定是没有满足这个条件。咱们来看一下面这种常见的情况,即service内部调用。
public class Demo {
public void methodA() {
this.methodB();
}
public void methodB() {
}
}
1、如果在methodA中加入:@Transactional,mehodB不加@Transactional,那么调用methodA,methodA的事物会生效,因为methodA默认的propagation为PROPAGATION_REQUIRED,此时methodB会加入到methodA中;

2、如果methodA与methodB都加上@Transactional,那么调用methodA,methodA的事物会生效,此时和 1 中情况一样,事物会生效,但是,其实methodA中通过this.methodB()的调用是没有触发spring 的事物,因此methodB的会加入到methodA中。

3、如果methodA配置@Transactional,methodB配置@Transactional( propagation = Propagation.REQUIRES_NEW ),那么调用methodA,此处的this指向目标对象,因此调用this.b()将不会执行b事务切面,即不会执行事务增强,因此b方法的事务定义“@Transactional(propagation = Propagation.REQUIRES_NEW)”将不会实施,即结果是b和a方法的事务定义是一样的一样是全部回滚。

总结:在一个Service内部,事务方法之间的嵌套调用,普通方法和事务方法之间的嵌套调用,都不会开启新的事务

原文链接:https://blog.csdn.net/weixin_37828327/article/details/99849316

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值