目录
1、事务的四大特性
2、事务并发问题
3、事务的传播行为
4、事务的隔离级别(类似数据库的事务隔离级别)
5、Spring管理事务的方式
5.1、编程式事务,在代码中硬编码
5.2、声明式事务,在配置文件中配置(基于XML和注解)
6、Spring事务的基本原理(代理)
7、事务不生效的场景
8、@Transaction和synchroized可以修饰同一个方法吗
原子性、一致性、隔离性、持久型。
从操作的角度来描述,事务中的各个操作要么都成功,要么都失败;
从数据的角度来描述,事务中的数据从一个一致性状态变换到另一个一致性状态。
比如:转账前A有1000, B有1000。转账后A+B也得是2000。
并发时,每个事务不能被其他事务的操作数据所干扰,多个并发事务之间互相隔离。
一个事务一旦被提交,那它对数据库中数据的改变就是永久性的。
脏读、幻读、更新丢失、不可重复读
一个事务读取了另一个事务尚未提交的数据。
初值age=10,事务A修改age=20,事务B读取age=20,事务A回滚age=10。
两个事务同时更新一行数据,最后一个事务的更新会覆盖前一个事务的更新。
事务A更新age=50 ->> 事务B更新age=30。事务A的更新被覆盖。
一个线程中的事务读到了另一个线程中已经提交的insert/delete的数据。
事务多次读取同一个数据,数据总量不一致。(前后多次读取,数据总量不一致)
事务A查询数据总量100条,事务B新增数据100条,数据A查询总量为200条。
一个线程中的事务读到了另一个线程中已经提交的update的数据。(前后内容不一样)
事务多次读取同一条数据,数据内容不一样。(前后多次读取,数据内容不一样)
事务A读age=10,事务B修改age=20(且提交事务),事务A读age=20。
不可重复读的重点是修改,幻读的重点是新增或删除。
一个事务方法被另一个事务方法调用的时候,当前事务方法如何运行。
多个具有事务控制的service互相调用时的事务传播问题。
如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。这是最常见的选择。
支持当前事务,如果当前没有事务,就以非事务方式执行。
使用当前的事务,如果当前没有事务,就抛出异常。
新建事务,如果当前存在事务,把当前事务挂起。
以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
以非事务方式执行,如果当前存在事务,则抛出异常。
如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。
1、获取连接:Connection con = DriverManager.getConnection()
2、开启事务:con.setAutoCommit(true/false)
3、执行业务代码CRUD
4、提交事务/回滚事务:con.commit()/con.rollback()
5、关闭连接con.close()
通过AOP功能,对@Transaction标注的类或方法前后进行拦截,将事务处理的相关功能编织到拦截的方法中。
Spring在启动时会去解析生成相关的Bean,在使用事务的时候,会为标注为@Transaction的类和方法生成一个代理,通过代理对这些类进行事务(提交、回滚)处理。
举例如下:
Synchronized只是锁当前代码块,当执行完Synchronized包含的代码块就开始释放锁;此时@Transactional还未提交!!!所以在并发条件下,上个事务还未提交的时候新的线程就已经可以进来了!!
Spring的@Transactional注解使用的是AOP来实现,也就是说被@Transactional注解的方法的事务是由Spring生成的一个代理类来处理的,当一个线程执行完该方法并释放锁后,代理类还没有提交事务前,别的线程是有机会进入到该方法中的,这样一来,就有几率访问到过期的数据,从而导致并发问题。
如果需要同时使用,可以用Synchronized包含所在的@Transactional方法即可。
以上内容为个人学习汇总,仅供学习参考,如有问题,欢迎在评论区指出,谢谢!
本文中截图来自于网络,如有侵权,请联系作者删除。