数据库事务及Spring对事物的处理方式

文章目录

      • 事务(数据库事务)
      • 事务的四大特性(ACID)
        • 原子性(Automicity)
        • 隔离性(Isolation)
        • 一致性(Consistency)
        • 持久性(Durability)
      • 数据库事务操作的三大读写问题
        • 脏读
        • 不可重复读
        • 幻读
      • 事务的隔离级别
      • Spring对事务的控制
        • Spring事务的传播行为
          • Propagation.REQUIRED
          • Propagation.SUPPORTS
          • Propagation.MANDATORY
          • Propagation.REQUIRES_NEW
          • Propagation.NOT_SUPPORTED
          • Propagation.NEVER
          • Propagation.NESTED
        • 编程式事务处理方法:
          • 自定义事务配置
          • Spring默认的事务提交策略

事务(数据库事务)

概述:由若干个数据库操作(CURD)组成的一个执行逻辑单位

事务的四大特性(ACID)

原子性(Automicity)

事务内的所有操作要么全部成功,要么全部失败

隔离性(Isolation)

不同的事务内的操作是互不影响的(如:一个方法并发10个开启了10个事务,10个事务的执行操作是一样的,且相互不干扰)

一致性(Consistency)

事务执行前后数据库的状态是一致的(符合数据库完整性约束)

数据库完整性:指的是数据库数据的正确性和有效性

  • 正确性:通俗的说数据库的数据是符合书库语法和规约(如在插入数据时会判断主键是否唯一,这个判断是因为存在数据库主键唯一约束规约的存在;是否允许空;唯一约束…)

  • 可靠性:数据库数据是对的(待补充)

持久性(Durability)

事务提交后,对数据库的操作是永久的,且不能被回滚

数据库事务操作的三大读写问题

脏读

读了其他事务未提交的数据(假数据)

不可重复读

在一个事务操作内操作某条数据,多次读取的数据结果不一样(一个事务操作内,其他事务被提交,数据被更改)(边读边写)

幻读

多个事务同时操作,读到数据不是自己开始写的数据(如:查询一个数据列表,读的时候有10条,写的时候发现有11条)(同时写和同时读)

脏读是读取了未提交的事务,不可重复读和幻读是读取了已经提交的事务

事务的隔离级别

读未提交read-uncommitted、读已提交read-committed、可重复读repearable-read、串行化serializable

MySql的默认隔离级别是 可重复读repearable-read 、 SqlServer和Oracle为读已提交

查询隔离级别:
MySql8前: select @@tx_isolation;

MySQL8: select @@transaction_isolation
会话的事务隔离级别 SELECT @@SESSION.transaction_isolation,@@SESSION.transaction_read_only;

事务隔离级别 脏读 不可重复读 幻读
读未提交 read-uncommitted
读已提交 read-committed
可重复读 repearable-read
串行化 serializable

Spring对事务的控制

Spring事务分类: 声明式事务(注解式@Transaction)、编程式事务(手动开启事务))

Spring事务的传播行为

Propagation.REQUIRED

代表当前方法支持当前的事务,且与调用者处于同一事务上下文中,回滚统一回滚(如果当前方法是被其他方法调用的时候,且调用者本身即有事务),如果没有事务,则自己新建事务,

Propagation.SUPPORTS

代表当前方法支持当前的事务,且与调用者处于同一事务上下文中,回滚统一回滚(如果当前方法是被其他方法调用的时候,且调用者本身即有事务),如果没有事务,则该方法在非事务的上下文中执行

Propagation.MANDATORY

代表当前方法支持当前的事务,且与调用者处于同一事务上下文中,回滚统一回滚(如果当前方法是被其他方法调用的时候,且调用者本身即有事务),如果没有事务,则抛出异常

Propagation.REQUIRES_NEW

创建一个新的事务上下文,如果当前方法的调用者已经有了事务,则挂起调用者的事务,这两个事务不处于同一上下文,如果各自发生异常,各自回滚

Propagation.NOT_SUPPORTED

该方法以非事务的状态执行,如果调用该方法的调用者有事务则先挂起调用者的事务

Propagation.NEVER

该方法以非事务的状态执行,如果调用者存在事务,则抛出异常

Propagation.NESTED

如果当前上下文中存在事务,则以嵌套事务执行该方法,也就说,这部分方法是外部方法的一部分,调用者回滚,则该方法回滚,但如果该方法自己发生异常,则自己回滚,不会影响外部事务,如果不存在事务,则与PROPAGATION_REQUIRED一样

编程式事务处理方法:

自定义事务配置
  • 使用了Spring的默认隔离级别和传播行为
    引入Spring默认的事务配置对象

    @Autowired
    private PlatformTransactionManager platformTransactionManager;

    @Autowired
    private TransactionDefinition transactionDefinition;

    //手动开启、提交和回滚事务
    TransactionStatus transactionStatus = platformTransactionManager.getTransaction(transactionDefinition);

    //提交事务
    platformTransactionManager.commit(transactionStatus);

    //回滚事务    
    platformTransactionManager.rollback(transactionStatus);
  • 自定义事务隔离级别,传播行为(一)
    DefaultTransactionDefinition def = new DefaultTransactionDefinition();  
    def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);  
    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);  
    //事务状态类,通过PlatformTransactionManager的getTransaction方法根据事务定义获取;获取事务状态后,Spring根据传播行为来决定如何开启事务
    TransactionStatus status =platformTransactionManager.getTransaction(def);  
  • 自定义事务隔离级别,传播行为(二)
    TransactionTemplate template = new TransactionTemplate(txManager);
    template.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);  
    //重写execute方法实现事务管理
    template.execute(new TransactionCallbackWithoutResult() {
        @Override
        protected void doInTransactionWithoutResult(TransactionStatus status) {
            jdbcTemplate.update(INSERT_SQL, "饿死");   //字段sd为int型,所以插入肯定失败报异常,自动回滚,代表TransactionTemplate自动管理事务
        }}
    );
Spring默认的事务提交策略

    @Autowired
    private TransactionTemplate transactionTemplate;

    Boolean isSuccess = transactionTemplate.execute(new TransactionCallback() {
        public Boolean doInTransaction(TransactionStatus status) {
            Boolean result = true;
            try {
                // TODO
            } catch (Exception e) {
                status.setRollbackOnly();
                result = false;
                // TODO
            }
            return result;
        }
    });

    回滚规则:执行方法中抛出了未检查异常或者调用了status.setRollbackOnly()方法,都会执行事务的回滚
    提交规则:方法执行完毕则默认提交事务

    TransactionCallback接口有一个子接口 TransactionCallbackWithoutResult,该接口中定义了一个 doInTransactionWithoutResult() 方法,TransactionCallbackWithoutResult 接口主要用于事务过程中不需要返回值的情况。当然,对于不需要返回值的情况,我们仍然可以使用 TransactionCallback 接口,并在方法中返回任意值即可.

    注意:在使用了@Transaction注解的方法内不可使用transactionTemplate, 否则会导致异常:Transaction rolled back because it has been marked as rollback-only。
    

源码(DataSourceTransactionManagerAutoConfiguration.class、TransactionTemplate.class)

@Bean
@ConditionalOnMissingBean({PlatformTransactionManager.class})
public DataSourceTransactionManager transactionManager(DataSourceProperties properties){
    DataSourceTransactionManager transactionManager = new DataSourceTransactionManager(this.dataSource);
    if (this.transactionManagerCustomizers != null){
    this.transactionManagerCustomizers.customize(transactionManager);}return transactionManager;
}

数据库事务及Spring对事物的处理方式_第1张图片

备注:有兴趣可以了解一下DataSourceTransactionManager的写法和原理。

@Bean
@ConditionalOnMissingBeanpublic 
TransactionTemplate transactionTemplate() {
    return new TransactionTemplate(this.transactionManager);
}

数据库事务及Spring对事物的处理方式_第2张图片

你可能感兴趣的:(SpringBoot事务,手动开启事务,编程式事务,数据库事务,事务特性,java程序高级设计,SpringBoot,SpringCloud)