事务隔离级别和传播行为、Spring如何管理事务

1.什么是事务

事务简单来说就是将一串操作一起提交,他们要么都执行成功,要么都执行失败。

事务四大特性:

  1. 原子性(Atomicity):事务是一个原子操作,操作要么都成功,要么都失败。
  2. 一致性(Consistency):事务执行前后,数据总量一致。(例如A、B共有100元,他们两之间一顿事务操作后总共还是只有100元,不多不少)
  3. 隔离性(Isolation):多个事务之间独立、互不干扰的。
  4. 持久性(Durability):一个事务提交后,对数据库的改变是持久性的,一经出事,概不退换。

2.并发事务的问题

在事务并发中产生的问题:

  1. 脏读(Dirty read):当一个事务对数据进行修改,还未提交到数据库时,另一个事务对这个数据进行了读取,我们真正想要的数据可能是修改后的数据,而读到的数据就是“脏数据”。
  2. 不可重复读(Unrepeatableread):当一个事务对数据两次读取,在第一次读取后另一个事务对数据进行了修改,那么第二次读取到的数据和第一次读取到的数据不同,两次结果不同叫做不可重复读。
  3. 幻读(Phantom read):当一个事务对数据两次读取,在第一次读取后另一个事务对数据进行了插入或者删除,那么第二次读取到的第一次读取中不存在的数据或者第二次读到的数据少了些数据,两次结果数据量不同叫幻读。

3.事务隔离级别

数据库中有四种隔离级别:

  1. 读取未提交(Read-UnCommitted):允许事务读取某事务中尚未提交的数据,可能导致脏读、不可重复读、幻读
  2. 读取已提交(Read-Committed):保证事务读取的数据是其他事务已经提交的,可能会导致不可重复读、幻读
  3. 可重复读(RepeaTable-Read):对同一属性的多次读取结果是一致。可能会导致幻读
  4. 可串行化(Serializable):对所有事务串行化读取,不会出现问题。

在Spring中除了以上四种隔离级别,还有一种默认的隔离级别,它默认使用数据库的事务隔离级别。MySQL的 InnoDB 存储引擎的默认支持的隔离级别是可重读。并且使用Next-Key Lock 锁算法处理幻读。(不同的隔离级别涉及到不同的锁,又涉及到知识盲区了…数据库锁学习提上日程)
在这里插入图片描述

4.Spring事务传播行为

事务传播行为定义了事务的控制范围。
支持当前事务的情况:

  1. PROPAGATION_REQUIRED:支持当前事务。如果当前存在事务,就加入该事务,否则新建一个事务。(Spring默认传播级别。上下文中有就用,没有就创建,适用于普通的事务场景)
  2. PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,否则以非事务方式执行。
  3. PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,否则抛出异常。
  4. PROPAGATION_NESTED:支持当前事务,如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行。否则创建一个事务。

不支持当前事务的情况:

  1. PROPAGATION_REQUIRES_NEW:无论当前存不存在事务,都创建新事务,如果当前存在事务就将当前事务挂起。
  2. PROPAGATION_NOT_SUPPORTED:无论当前存不存在事务,都以非事务方式执行操作,如果当前存在事务就将当前事务挂起。
  3. PROPAGATION_NEVER:无论当前存不存在事务,都以非事务方式执行,如果当前存在事务则抛出异常。

5.Spring怎么管理事务

Spring有两种管理事务方式,即编程式事务和声明式事务。编程式事务在代码中编码实现,声明式事务在XML文件中配置或者使用注解配置。

事务管理器器接口:提供了获取事务方法、事务提交、事务回滚三个基本的方法。

public interface PlatformTransactionManager {
    TransactionStatus getTransaction(TransactionDefinition var1) throws TransactionException;

    void commit(TransactionStatus var1) throws TransactionException;

    void rollback(TransactionStatus var1) throws TransactionException;
}
  1. 事务管理器种获取事务状态时传入了一个TransactionDefinition,TransactionDefinition中定义了7种事务的传播行为和5种事务传播行为以及一些事务常用方法。
public interface TransactionDefinition {
	//七种事务传播行为
    int PROPAGATION_REQUIRED = 0;
    int PROPAGATION_SUPPORTS = 1;
    int PROPAGATION_MANDATORY = 2;
    int PROPAGATION_REQUIRES_NEW = 3;
    int PROPAGATION_NOT_SUPPORTED = 4;
    int PROPAGATION_NEVER = 5;
    int PROPAGATION_NESTED = 6;
    //四种事务隔离级别
    int ISOLATION_DEFAULT = -1;
    int ISOLATION_READ_UNCOMMITTED = 1;
    int ISOLATION_READ_COMMITTED = 2;
    int ISOLATION_REPEATABLE_READ = 4;
    int ISOLATION_SERIALIZABLE = 8;
    //超时时间
    int TIMEOUT_DEFAULT = -1;
	//获取当前事务传播行为
    int getPropagationBehavior();
	//获取当前事务隔离级别
    int getIsolationLevel();
	//获取
    int getTimeout();
	//是否只读
    boolean isReadOnly();
	//当前事务名称
    String getName();
}
  1. 事务状态TransactionStatus,里面提供了获取当前事务的一些状态,是否是新的事务、是否有保存点等。
public interface TransactionStatus extends SavepointManager, Flushable {
	//是否是新事务
    boolean isNewTransaction();
	//是否有保存点
    boolean hasSavepoint();
	//标记为回滚
    void setRollbackOnly();
	//是否已被标记为回滚
    boolean isRollbackOnly();
}
1、编程式事务案例:
    @Autowired
    //获得一个TransactionManager实例
    private DataSourceTransactionManager txManager;

    public Integer test() {
        //获取事务定义
        DefaultTransactionDefinition defs = new DefaultTransactionDefinition();
        //设置事务传播行为
        defs.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
        //设置事务隔离级别
        defs.setIsolationLevel(TransactionDefinition.ISOLATION_REPEATABLE_READ);
        //获得事务状态
        TransactionStatus ts = txManager.getTransaction(defs);
        try {
            //...数据库操作
            txManager.commit(ts);
        } catch (Exception e) {
            txManager.rollback(ts);
        }

    }
2、声明式事务案例

声明式事务就是将管理器的创建包括事务的属性配置在XML文件中,然后使用在需要使用事务的方法上添加@Transactional注解。

Transactional 注解的源码如下,一般情况下只需要设置一个导致回滚的异常数组名,也可以设置事务传播级别和隔离级别等。

public @interface Transactional {
    @AliasFor("transactionManager")
    String value() default "";

    @AliasFor("value")
    String transactionManager() default "";
	//设置的事务传播行为
    Propagation propagation() default Propagation.REQUIRED;
	//设置事务隔离级别
    Isolation isolation() default Isolation.DEFAULT;
	//设置事务超时时间
    int timeout() default -1;
	//设置事务是否只读
    boolean readOnly() default false;
	//导致事务回滚的异常类数组
    Class<? extends Throwable>[] rollbackFor() default {};
	//导致事务回滚的异常类数组名
    String[] rollbackForClassName() default {};
	//不会导致事务回滚的异常类数组
    Class<? extends Throwable>[] noRollbackFor() default {};
	//不会导致事务回滚的异常类数组名
    String[] noRollbackForClassName() default {};
}

以下是一个声明式事务例子:

xml中的配置文件如下

   <tx:annotation-driven transaction-manager="txManager"/>

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

该注解实现的功能与上例中编程式事务实现功能一致,使用Transactional的注解实现事务属性设置(一般默认就行,不用特别设置),加上rollbackFor={Exception.class}后不管运行时异常还是非运行时异常,都会进行回滚,不加的话只会在运行时异常菜回滚,。

    @Transactional(propagation=Propagation.REQUIRES_NEW,
            isolation=Isolation.REPEATABLE_READ,
            rollbackFor={Exception.class})
    public Integer test() {
            //...数据库操作
    }

在SpringBoot中更加简便,SpringBoot的启动类里面含有@EnableTransactionManagement注解,自动开启事务支持,只需要在使用的地方加上@Transactional即可,SpringBoot真香!

6.分布式事务

在分布式系统中,多个系统可能无法公用一个数据库,所以无法简单的使用普通事务进行处理。所以平时项目开发过程中经量避免出现分布式事务,在分表的时候尽量把相关的业务数据存入一个数据库中。

1、补偿事务(TCC)

TCC(Try-Confirm-Cancel)采用的补偿机制,其核心思想是:针对每个操作,都要注册一个与其对应的确认和补偿(撤销)操作。它分为三个阶段:

Try 阶段主要是对业务系统做检测及资源预留

Confirm 阶段主要是对业务系统做确认提交,Try阶段执行成功并开始执行 Confirm阶段时,默认 Confirm阶段是不会出错的。即:只要Try成功,Confirm一定成功。

Cancel 阶段主要是在业务执行错误,需要回滚的状态下执行的业务取消,预留资源释放。

举个例子,假入 Bob 要向 Smith 转账,思路大概是:
我们有一个本地方法,里面依次调用
1、首先在 Try 阶段,要先调用远程接口把 Smith 和 Bob 的钱给冻结起来。
2、在 Confirm 阶段,执行远程调用的转账的操作,转账成功进行解冻。
3、如果第2步执行成功,那么转账成功,如果第二步执行失败,则调用远程冻结接口对应的解冻方法 (Cancel)。

举个简单的例子:如果你用 100 元买了一瓶水, Try 阶段:你需要向你的钱包检查是否够 100 元并锁住这 100 元,水也是一样的。

如果有一个失败,则进行 Cancel(释放这 100 元和这一瓶水),如果 Cancel 失败不论什么失败都进行重试 Cancel,所以需要保持幂等。

如果都成功,则进行 Confirm,确认这 100 元被扣,和这一瓶水被卖,如果 Confirm 失败无论什么失败则重试(会依靠活动日志进行重试)。

原创文章 49 获赞 55 访问量 8398

猜你喜欢

转载自blog.csdn.net/tc979907461/article/details/105511246