Spring事务及事务传播机制(2)

@Transactional详解

我们主要学习@Transactional注解当中的三个常见属性:

1.rollbackFor: 异常回滚特性. 指定能够触发事务回滚的异常类型. 可以指定多个异常类型.

2.Isolation:事务的隔离级别. 默认值为Isolation.DEFAULT

3.propagation: 事务的传播机制. 默认为Propagation.REQUIRED.

rollbackFor

@Transactional 默认只在遇到运行时异常和Error才会进行回滚, 非运行时异常不回滚. 即Exception的子类中, 除了RuntimeException及其子类.

之前我们通过制造一个运行时异常, 发现事务回滚了, 接下来把异常改为如下代码:

    @Transactional
    @RequestMapping("/registry")
    public String registry(String name, String password) throws IOException {
        //用户注册
        userService.registryUser(name, password);
        log.info("用户数据插入成功");
        if(true) {
            throw new IOException();
        }
        return "注册成功";
    }

运行程序:

发现虽然程序抛出了异常, 但是事务仍被提交:

如果需要所有的异常都回滚, 需要配置@Transactional注解当中的rollbackFor属性, 通过rollbackFor这个属性指定出现何种异常类型时事务进行回滚.

@Transactional(rollbackFor = Exception.class)

运行代码, 观察现象:

发现这时事务进行了回滚.

结论:

在Spring事务管理中, 默认只在遇到运行时异常RuntimeException和Error时才会进行回滚.

如果需要回滚指定类型的异常, 可以通过rollbackFor属性来指定

事务隔离级别

回顾: 并发读数据库可能引发的问题

1.脏读: 指一个事务A读取到了事务B还没有提交的数据, 在之后事务B进行了修改, 这时候事务A读到的数据称为脏数据, 也叫脏读. (解决方案: 给写操作加锁, 即一个事务在没有提交之前, 不能被读取).

2.不可重复读: 一个事务先后两次读取到的数据不一致, 可能是两次读取过程中插入了一个新的事务更新了原有的数据, 注:侧重于修改(解决方案: 给读操作加锁, 即一个事务在没有读完的时候不会插入其它的数据).

3.幻读: 同一个事务中, 多次查询的结果集返回不一致. 比如事务A查询了几列数据, 而事务B在此时又插入了新的几列数据(注:侧重于新增或删除),先前的事务在接下来的查询中, 就会发现几列是它先前所没有的, 这就是幻读. (解决方案: 进一步提高事务之间的隔离性, 即串行化).

MySQL数据库事务隔离级别

1.读未提交: 最低的隔离级别, 在该级别内可以看到其它事务未提交的数据.

因为其它未提交的数据可能会发生回滚, 但是在该级别下仍然是可以读到的, 这个读到的就是脏数据.

2.读已提交: 在该级别内, 一个事务只能读取其它事务中已提交的数据(相当于加写锁).

 在该隔离级别内不会存在脏读的问题. 但由于在事务的执行中可以读取到其它事务提交的结果,  所以在不同时间读取到的数据可能不一致.

3.可重复读: 事务不会读到其它事务对已有数据的修改, 即使其它事务已经提交. 也就可以确保同一事务多次查询到的结果一致, 但是对于其它事务新插入的数据, 是可以感知到的. 这就引发了幻读问题. 可重复读, 是MySQL中默认的事务隔离级别(相当于加读锁和写锁).

比如此级别的事务正在执行时, 另一个事务中新增了一条数据, 但是由于每次读取的时候结果都一样, 所以导致查询不到这条数据. 

 4.串行化: 是事务的最高隔离级别, 它会强制事务排序, 使之不会发生冲突. 但是因为资源消耗很大, 所以不太常用.

Spring中的事务隔离级别:

1.Isolation.DEFAULT: 以连接的数据库的隔离级别为主.

2.Isolation.READ_UNCOMMITTED:读未提交

3.Isolation.READ_COMMITED: 读已提交.

4.Isolation.REPEATABLE_READ: 可重复读

5.Isolation.SERIALIZABLE: 串行化.

spring中的事务隔离级别也可以通过类似之前的rollbackFor的方式设置:

@Transactional(isolation = Isolation.READ_COMMITTED)

Spring事务传播机制

什么是事务传播机制

事务传播机制就是: 多个事务方法存在调用关系时, 事务是如何在这些方法间进行传播的.

比如有两个方法A, B都被@Transactional修饰, A方法调用B方法, 此时B方法运行时, 是加入A的事务, 还是创建一个新的事务呢?

这就涉及到了事务的传播机制.

事务隔离级别解决的是多个事务同时调用一个数据库的问题.

而事务传播机制解决的hi一个事务在多个节点(方法)中传递的问题

事务的传播机制有哪些?

@Transactional注解支持事务传播机制的设置, 通过propagation属性来指定传播行为.

 Spring事务传播机制有以下7种(以下结合一对新人要结婚的例子来说明):

1.Propagation.REQUIRED: 默认的事务隔离级别. 如果当前存在事务, 则加入该事务. 如果当前没有事务, 则创建一个新的事务.(需要有房子, 如果你有房, 我们就一起住, 如果你没房, 我们就一起买房).

2.Propagation.SUPPORTS: 如果当前存在事务, 则加入该事务. 如果当前没有事务, 则继续以非事务的方式继续执行.(可以有房子, 如果你有房, 那就一起住, 如果没房, 那就租房).

3.Propagation.MANDATORY: 如果当前存在事务, 则加入该事务. 如果当前没有事务, 则抛出异常.(必须有房子, 要求必须有房, 如果没房就不结婚).

4.Propagation.REQUIRES_NEW: 创建一个新的事务. 如果当前存在事务, 则把当前事务挂起.

(必须买新房, 不管你有没有房, 必须要两个人一起买房. 即使有房也不住)

5.Propagation.NOT_SUPPORTED: 以非事务的方式运行, 如果当前存在事务, 则把当前事务挂起. (不需要房, 不管你有没有房, 我都不住, 必须租房)

6,Propagation.NEVER: 以非事务的方式运行, 如果当前存在事务, 则抛出异常(不能有房子)

7.Propagation.NESTED: 如果当前存在事务, 则创建一个事务作为当前事务的嵌套事务运行, 如果没有事务, 则取值等价于Propagation.REQUIRED.(如果有房, 则以房子为根据地, 做点下生意.)

  • 21
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
事务隔离级别是指多个事务并发执行时,一个事务对其他事务的可见性和影响程度的控制。Spring框架支持四个事务隔离级别: 1. 未提交读(READ UNCOMMITTED):最低级别,一个事务可以读取未提交的数据,会导致脏读,不可重复读和幻读问题的出现。 2. 提交读(READ COMMITTED):一个事务只能读取已提交的数据,可以避免脏读问题,但可能导致不可重复读和幻读问题。 3. 可重复读(REPEATABLE READ):在一个事务中多次读取同一数据时,结果保持一致,避免了不可重复读问题。但仍然可能存在幻读问题。 4. 串行化(SERIALIZABLE):最高级别,通过确保事务串行执行来避免脏读、不可重复读和幻读问题。但会降低并发性能。 传播机制是指在调用多个事务方法时,如何处理事务传播Spring框架提供七种传播行为: 1. REQUIRED:如果当前没有事务,就创建一个新事务;如果已存在事务,则加入该事务。 2. SUPPORTS:支持当前事务,如果当前没有事务,就以非事务方法执行。 3. MANDATORY:强制要求存在当前事务,如果没有事务就抛出异常。 4. REQUIRES_NEW:创建一个新事务,并暂停当前事务(如果有)。 5. NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,则将其挂起。 6. NEVER:以非事务方式执行操作,如果当前存在事务,则抛出异常。 7. NESTED:在当前事务的控制下执行一个嵌套事务,如果不存在当前事务,则创建一个新事务。嵌套事务可以独立提交或回滚,但在外部事务提交时才会生效。 通过选择合适的事务隔离级别和传播机制,可以确保事务的数据一致性、安全性和性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值