【Spring】 ---- 数据库事务管理

目录

1.Spring数据库事务管理器的设计
2.声明式事务
3.数据库的相关知识
4.选择隔离级别和传播行为

1.Spring数据库事务管理器的设计

在Spring中数据库事务是通过PlatformTransactionManager进行管理的

1.1 TransactionTemplate源码

  • 事务的创建、提交和回滚是听过PlatformTransactionManager接口来实现的
  • 当事务产生异常时会回滚事务
  • 当无异常时,会提交事务

1.2 事务管理器的实现
在这里插入图片描述
常用的是DataSourceTransactionManager,继承了AbstractPlatformTransactionManager,又实现了PlatformTransactionManager(该接口方法有:获取事务状态、提交事务、回滚事务)

1.3 配置事务管理器

<!--配置数据源-->
    <bean name="dataSource" class="com.alibaba.druid.pool.DruidDataSource">
        <property name="driverClassName" value="${db.driverClassName}"/>
        <property name="url" value="${db.url}"/>
        <property name="username" value="${db.username}"/>
        <property name="password" value="${db.password}"/>
    </bean>

    <!--配置数据源事务管理器-->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"/>
    </bean>

2.声明式事务

声明式事务的流程

代码例子

@Service(value = "roleService")
public class RoleServiceImpl implements RoleService {

    @Autowired
    private RoleMapper roleMapper;
    
    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, timeout = 3)
    public int insertRole(Role role) {
        return roleMapper.insertRole(role);
    }
    
}

当roleMapper的insert方法抛出异常时,Spring就会回滚事务,如果成功,就提交事务

3.数据库的相关知识

3.1 数据库事务ACID特性
数据库事务正确执行的4个基础要素是:原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)

  • 原子性:整个事务中的所有操作,要么全部成功,要么全部不完成
  • 一致性:指一个事务可以改变封装状态。事务必须始终保持系统处于一致的状态,不管在任何给定的时间并发事务有多少。
  • 隔离性:指两个事务之间的隔离程度
  • 持久性:在事务完成以后,该事务对数据库所做的更改便持久保存在数据库之中,并不会被回滚

3.2 丢失更新

  • 第一类丢失更新
    两个事务并发,一个回滚、一个提交成功导致不一致
    事务回滚覆盖另外一个事务的更新
  • 第二类丢失更新
    不同的事务中,两个事务无法探知对方的事务操作,导致不一致
    事务提交覆盖另外一个事务的更新

3.3 隔离级别

隔离级别可以在不同程度上减少丢失更新
隔离级别定义为4层,分别是:脏读(dirty read)、读/写提交(read commit)、可重复读(repeatable read)和序列化(Serializable)

  • 脏读: 事务一可以读取事务二未提交的事务
  • 读/写提交: 一个事务只能读取另一个事务已经提交的数据(消除了脏读带来的问题,带来了不可重复读问题)
  • 可重复读: 在同一个事务内的查询都是事务开始时刻一致的,针对数据库同一条记录而言。可重复读会使得同一条数据库记录的读/写按照一个序列化进行操作,不会产生交叉情况,但是如果数据库同时对多条记录进行读/写,这个时候会带来幻读问题
  • 序列化: 一种让SQL按照顺序读/写的方式,消除数据库事务之间并发产生数据不一致的问题。

各类隔离级别和产生的现象

隔离级别脏读不可重读幻读
脏读
读/写提交×
可重复读××
序列化×××

4.选择隔离级别和传播行为

4.1 选择隔离级别
在互联网应用中,不但要考虑数据库数据的一致性,而且要考虑系统的性能。
从脏读到序列化,系统性能直线下降。
大部分场景下,企业会选择读/写提交的方式设置事务。(有助于提高并发,又压制了脏读,但对于数据一致性问题没有解决)

使用读/写提交隔离级别:

@Autowired
    private RoleMapper roleMapper;

    @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, timeout = 3)
    public int insertRole(Role role) {
        return roleMapper.insertRole(role);
    }

@Transactional隔离级别默认值是:Isolation.DEFAULT

  • MySQL支持4种隔离级别,默认的是可重复读
  • Oracle只能支持读/写提交和序列化隔离级别,默认的是读/写提交

4.2 传播行为

传播行为是指方法之间的调用事务策略的问题。

Spring的7种传播行为

传播行为含义备注
REQUIRED当方法调用时,如果不存在当前事务,那么就创建事务;如果之前的方法已经存在事务了,就沿用之前的事务Spring默认传播行为
SUPPORTS当方法调用时,如果不存在当前事务,那么就不启用事务;如果存在当前事务,那么就沿用当前事务
MANDATORY方法必须在事务内运行如果不存在当前事务,那么就抛出异常
REQUIRES_NEW无论是否存在当前事务,方法都会在新的事务中运行事务管理器会打开新的事务运行该方法
NOT_SUPPORTED不支持事务,如果不存在当前事务也不会创建事务;如果存在当前事务,则挂起它,直至该方法结束后才恢复当前事务适用于那些不需要事务的SQL
NEVER不支持事务,只有在没有事务的环境中才能运行它如果方法存在当前事务,则抛出异常
NESTED嵌套事务,调用方法如果抛出异常只回滚自己内部执行的SQL,而不回滚主方法的SQL如果当前数据库支持保存点,那么就在当前事务上使用保存点技术;如果发生异常则将方法内执行的SQL回滚到保存点,而不是全部回滚
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值