专业编程教程与实战项目分享平台

网站首页 > 技术文章 正文

Spring事务管理 Spring事务管理的实现源码

ins518 2024-10-21 07:58:54 技术文章 13 ℃ 0 评论

事务的四大特性

  1. 原子性:事务中的所有操作都是不可分割的原子单位。事务中的所有操作要么全部执行成功,要么全部执行失败。
  2. 一致性:事务执行后,数据库状态与其他与其他业务规则保持一致。如转账业务,无论事务执行成功与否,参与转账的两个账号余额之和应该是不变的。
  3. 隔离性:隔离性是指在并发操作中,不同事务之间应该隔离开来,使每个并发中的事务不会相互干扰。
  4. 持久性:一旦事务提交成功,事务中所有的数据操作都必须被持久化到数据库中,即使提交事务后,数据库马上崩溃,在数据库重启时,也必须能保证通过某种机制恢复数据。

事务出现的问题

  1. 脏读(dirty read):一个事务读取到另外一个事务中未提交的更新数据,即读取到了脏数据。
  2. 不可重复读(unrepeatable read):对同一记录的两次读取不一致,因为另一事务对该记录做了修改。
  3. 幻读(phantom read):又称虚读,事务在两次查询返回的数据中发生了数据的缺少或增加,因为另一事务插入或删除了一条记录。

事务四大隔离级别

SERIALIZABLE(串行化):

  • 不会出现任何问题,因为它是对同一数据的访问时串行的,非并发访问!
  • 性能最差!

REPEATABLE READ(可重复读):

  • 防止脏读和不可重复读,不能处理幻读问题!
  • 性能较SERIALIZABLE好。

READ COMMITTED(读已提交数据):

  • 防止脏读,没有处理不可重复读和幻读;
  • 性能较前两种更佳。

READ UNCOMMITTED(读未提交数据):

  • 可能出现上述所有的事务并发问题;
  • 性能在四种隔离中最优!

MySQL的默认隔离级别为REPEATABLE READ!Oracle的默认隔离级别为READ COMMITTED

事务七种传播行为

事务传播行为(propagation behavior)指的就是当一个事务方法被另一个事务方法调用时,这个事务方法应该如何进行。 例如:methodA事务方法调用methodB事务方法时,methodB是继续在调用者methodA的事务中运行呢,还是为自己开启一个新事务运行,这就是由methodB的事务传播行为决定的。

  1. PROPAGATION_REQUIRED:如果当前没有事务,就创建一个新事务,如果当前存在事务,就加入该事务,该设置是最常用的设置。
  2. PROPAGATION_SUPPORTS:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就以非事务执行
  3. PROPAGATION_MANDATORY:支持当前事务,如果当前存在事务,就加入该事务,如果当前不存在事务,就抛出异常。
  4. PROPAGATION_REQUIRES_NEW:创建新事务,无论当前存不存在事务,都创建新事务。
  5. PROPAGATION_NOT_SUPPORTED:以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
  6. PROPAGATION_NEVER:以非事务方式执行,如果当前存在事务,则抛出异常。
  7. PROPAGATION_NESTED:如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则按 REQUIRED 属性执行

Spring事务分类

声明式事务

Spring 的声明式事务管理是建立在 Spring AOP 机制之上的,其本质是对目标方法前后进行拦截,并在目标方法开始之前创建或者加入一个事务,在执行完目标方法之后根据执行情况提交或者回滚事务。

简单地说,声明式事务是编程式事务 + AOP 技术包装,使用注解进行扫包,指定范围进行事务管理。声明式事务管理要优于编程式事务管理,这正是 Spring 倡导的非侵入式的开发方式。

示例:

@Transactional
public void test3()
    // TODO 业务代码
 }

编程式事务

在 Spring 出现以前,编程式事务管理对基于 POJO 的应用来说是唯一选择。我们需要在代码中显式调用 beginTransaction()、commit()、rollback() 等事务管理相关的方法,这就是编程式事务管理。

简单地说,编程式事务就是在代码中显式调用开启事务、提交事务、回滚事务的相关方法,因此代码侵入性较大。

示例:

@Autowired
private PlatformTransactionManager transactionManager;
public void test3() {
    TransactionStatus transactionStatus = this.transactionManager.getTransaction(new DefaultTransactionDefinition());
    try {
          // TODO 业务代码
          // 提交事务
          this.transactionManager.commit(transactionStatus);
    } catch (Exception e) {
          // 回滚事务
          this.transactionManager.rollback(transactionStatus);
    }
}

Spring 事务的原理是使用 AOP 环绕通知 和 异常通知。

注意:在使用 Spring 事务时不能使用 try-catch 进行异常捕获,要将异常抛给外层,使其进行异常拦截,触发事务机制。否则导致事务失效,参考下篇Spring事务失效原因汇总

Spring事务三大接口

PlatformTransactionManager 事务管理器

TransactionDefinition事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则)

TransactionStatus 事务的一些状态信息,如是否一个新的事务、是否已被标记为回滚

1:事务管理器
PlatformTransactionManager

真正用来管理事务的接口,包含 事务的提交,回滚等信息。Spring 为不同的持久层框架 提供了 不同的实现类。然后根据不同的持久层框架 去选择不同的 平台事务管理器实现类。如果持久层框架使用jdbc,就选择实现类
DataSourceTransactionManager。如果持久层使用Hibernate,就选择实现类HibernateTransactionManager。

public interface PlatformTransactionManager extends TransactionManager {
     
     //根据事务定义TransactionDefinition,获取事务
     TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
      throws TransactionException;
      
      //提交事务
      void commit(TransactionStatus status) throws TransactionException;

      // 回滚事务 
      void rollback(TransactionStatus status) throws TransactionException;
  }

2:事务定义接口TransactionDefinition

事务的定义包括: 事务的隔离级别,事务的传播属性,超时时间设置,是否只读。

事务的隔离级别是数据库本身的事务功能,事务的传播属性则是spring为我们提供的功能,该接口的实现
DefaultTransactionDefinition,默认的事务定义:

1.事务的传播属性为PROPAGATION_REQUIRED,即当前没有事务的时候,创建一个,如果有则使用当前事务

2.事务的隔离级别采用底层数据库默认的隔离级别

3.超时时间采用底层数据库默认的超时时间

4.是否只读为false

public class DefaultTransactionDefinition implements TransactionDefinition, Serializable {
    private int propagationBehavior = PROPAGATION_REQUIRED;
    private int isolationLevel = ISOLATION_DEFAULT;
    private int timeout = TIMEOUT_DEFAULT;
    private boolean readOnly = false;
    //略
}

3:事务运行状态TransactionStatus

public interface TransactionStatus extends TransactionExecution, SavepointManager, Flushable {
  /**   
    * 是否有保存点  
   */
  boolean hasSavepoint();
  void flush();
}

TransactionStatus它继承了SavepointManager接口,SavepointManager是对事务中上述保存点功能的封装,如下:

public interface SavepointManager {
  // 创建一个保存点
  Object createSavepoint() throws TransactionException;
  // 释放一个保存点
  void releaseSavepoint(Object savepoint) throws TransactionException;
  // 回滚一个保存点
  void rollbackToSavepoint(Object savepoint) throws TransactionException;
}

TransactionStatus本身更多存储的是事务的一些状态信息:

  • 是否是一个新的事物
  • 是否有保存点
  • 是否已被标记为回滚

事务的五种状态

1. 活动状态
事务在执行时的状态叫活动状态。

2. 部分提交状态
事务中最后一条语句被执行后的状态叫部分提交状态。

3. 失败状态
事务不能正常执行的状态叫失败状态。

4. 提交状态
事务在部分提交后,将往硬盘上写入数据,当最后一条信息写入后的状态叫提交状态。进入提交状态的事务就成功完成了。

5. 中止状态
事务回滚并且数据库已经恢复到事务开始执行前的状态叫中止状态。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表