2023-08-25 15:06:21 星期五

事务四个特性ACID

  • A: Atomic原子性
  • C: Consistency 一致性,

Consistency ensures that a transaction can only bring the database from one valid state to another, maintaining database invariants: any data written to the database must be valid according to all defined rules, including constraints, cascades,triggers, and any combination thereof. This prevents database corruption by an illegal transaction, but does not guarantee that a transaction is correct.

  • I: Isolation隔离性,各个事务互相隔离,互不影响
  • D: Durability事务结束后对数据的修改是永久性的,即使宕机了,数据也不会丢失

我对于一致性的理解:
数据从一种状态变到另一种状态,保持总量不变,切要符合我们预订的规则,比如A向B转了10块钱,那A的阅一定少了10,B的余额一定多了10; 另一种情况A的余额90块钱,向B转100块钱,不符合规则,所以一定要回滚的。

spring事务的两种方式

编程式事务

参见文章

  • 通过PlatformTransactionManager控制事务

  • 通过TransactionTemplate控制事务

声明式事务

@Transactional注解,他的实现是基于AOP的,在方法执行前创建或者加入事务,在方法执行后根据执行情况决定是提交还是回滚事务,优点就是不需要通过编程的方式来管理事务,不需要在代码中掺杂很多事务管理的代码。

事务隔离级别

四种隔离级别,之前在mysql里讲过啦,详细的看
mysql并发问题及隔离级别

  • 读未提交
    不能避免脏读,不可重复读,和幻读的问题

  • 读已提交
    解决了脏读的问题,但没有解决幻读和不可重复读的问题

  • 可重复读
    解决了不可重复读的问题,但没有解决幻读的问题

  • 串行化
    事务串行执行,解决了上述的所有问题,但效率很低啊

事务传播等级

A方法调用B方法

  • REQUIRED
    /**
     * Support a current transaction, create a new one if none exists.
     * Analogous to EJB transaction attribute of the same name.
     * <p>This is the default setting of a transaction annotation.
     */
REQUIRED(TransactionDefinition.PROPAGATION_REQUIRED),

这是spring默认的传播等级
如果当前方法存在事务,就加入当前事务,如果不存在,就创建新事务。
– 当父事务回滚则子事务回滚

- ==当子事务回滚,不管父事务是否捕捉异常,都会回滚。==
@SneakyThrows
@Override
@Transactional(rollbackFor = Exception.class)
public void testTrans() {
    log.info("trans--------------------------------k");
    userNumsService.save(new UserNumsPO().setDescription("test hello1").setNums(1).setUserId(IdUtil.getSnowflakeNextId()));
    try {
        userNumsService.testRequiredTrans();
    }catch (Exception e){
        log.info("捕捉到子事务异常");
    }
}

@SneakyThrows
@Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
public void testRequiredTrans(){
    log.info("trans--------------------------------k");
    this.save(new UserNumsPO().setDescription("requiredTrans").setNums(2).setUserId(IdUtil.getSnowflakeNextId()));
    if (1/1==1){
        throw new  Exception();
    }
}
  • REQUIRES_NEW
    /**
     * Create a new transaction, and suspend the current transaction if one exists.
     * Analogous to the EJB transaction attribute of the same name.
     * <p><b>NOTE:</b> Actual transaction suspension will not work out-of-the-box
     * on all transaction managers. This in particular applies to
     * {@link org.springframework.transaction.jta.JtaTransactionManager},
     * which requires the {@code javax.transaction.TransactionManager} to be
     * made available to it (which is server-specific in standard Java EE).
     * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager
     */
// 创建一个新的事务,并在存在当前事务的情况下挂起当前事务。
REQUIRES_NEW(TransactionDefinition.PROPAGATION_REQUIRES_NEW),

开启一个新事务,新的事务和原有的事务互不影响,但要注意捕捉子事务的异常,防止因为子事务的异常导致父事务回滚。子事务抛出了异常,子事务就会回滚。

  • NESTED
    /**
     * Execute within a nested transaction if a current transaction exists,
     * behave like {@code REQUIRED} otherwise. There is no analogous feature in EJB.
     * <p>Note: Actual creation of a nested transaction will only work on specific
     * transaction managers. Out of the box, this only applies to the JDBC
     * DataSourceTransactionManager. Some JTA providers might support nested
     * transactions as well.
     * @see org.springframework.jdbc.datasource.DataSourceTransactionManager
     */
    NESTED(TransactionDefinition.PROPAGATION_NESTED);

这个传播特性和REQUIRED有点像,当前方法存在事务时,则加入当前事务嵌套执行

- 父事务回滚,则子事务也回滚。

- 子事务回滚,则父事务是否回滚看是否捕捉了异常,捕捉了则不会滚,没有捕捉则回滚。(这个和REquired是不同的)
事务传播级别 特性
REQUIRED 如果当前不存在事务,创建一个新事物,如果存在事务则加入到当前事务中。如果父事务回滚则子事务回滚,如果子事务回滚,则父事务不管有没有捕获异常也会回滚
REQUIRES_NEW 无论当前方法是否存在事务都创建一个新事物,与当前事务是互相隔离的,只要父事务捕获了异常,子事务都回滚不会导致父事务的回滚
NESTED 当前方法存在事务时,子事务会嵌套执行,和REQUIRED有点像,但是这个父事务只要捕获异常,子事务回滚不会导致父事务回滚

华丽的分割线


  • SUPPORT
简单来说,SUPPORTS 传播行为用于指定方法在存在事务的情况下支持使用事务,但如果没有事务存在,也可以在非事务环境下执行。这允许方法根据上下文在事务和非事务之间切换。
  • MANDATORY
简单来说,MANDATORY 传播行为用于指定方法必须在一个事务上下文中执行,如果当前没有一个事务存在,将会抛出异常。这个传播行为适用于需要确保方法在事务中执行的场景,如果没有事务,就会阻止方法的执行。
  • NOT_SUPPORTED
NOT_SUPPORTED 传播行为用于在方法执行时强制要求不在事务中执行,如果当前存在一个事务,则将其挂起,使方法在没有事务的上下文中执行。这允许方法完全脱离事务控制,以适应一些特定的业务场景
  • NEVER
NEVER 传播行为在方法执行时强制要求没有当前事务存在。如果方法调用发生在一个已经存在的事务上下文中,那么将会抛出异常,通知开发者该方法不应该在事务上下文中执行。

事务失效

1.首先数据库要支持事务
2.不是public方法
3. 出现了自调用问题 调该类自己的方法,而没有经过 Spring 的代理类,默认只有在外部调用事务才会生效,
4. 数据源没有配置事务管理器
5. 异常类型没有被捕获(指定了rollbackFor异常回滚的类型)
6. 手动try catch住了,异常没有抛出来
7. bean对象没有被spring管理
分类: java

0 条评论

发表评论

Avatar placeholder

您的电子邮箱地址不会被公开。 必填项已用*标注

ICP备案号: 辽ICP备20003309号