数据库事务以及springboot中的事务注解

60 阅读3分钟

数据库事务

数据库事务是一组sql语句的执行,他们作为一个单一的单元来进行执行,要么全部执行,要么全部不执行,这样可以确保数据的一致性和完整性,最本质的特征是数据库事务满足acid原则

  • 什么是acid原则

acid原则分别是原子性,一致性,隔离性,持久性

总的来说原子性就是要么执行成功要么执行失败,只要发生错误那么事务就会回滚。

一致性就是数据库状态只能从一个一致性状态转移到另外一个一致性状态,简单理解就是不破坏数据库的完整性,包括数据库中数据的相关约束。举个简单例子,假如你在银行存有1000元,你要转账给另外一个人。你转账800元,你发现你的余额被扣了,账户剩下200元,那另外一个人的账户应该增加800元的,但是出问题了,转账出故障了(可能银行那边钱不够了)。这个时候很明显,如果执行成功(对方还是没有收到800元)那么数据库就不是一致性状态了,所以必须回滚,提醒操作失败。

隔离性就是数据库支持很多个事务一起运行,多个事务之间互不影响。

持久性就是事务在执行成功之后,对数据库中的update或者是insert都是永久性的,会被写入磁盘,这种情况即使是系统故障也是不可改变的。

SpringBoot事务

数据库事务的这些隔离级别在数据库中可以设置,那么在编程中,我们一般会颗粒度到一个方法,这个方法的执行内容(业务)加入到一个事务中,然后方法和方法之间的事务关系是什么样的。

@Transactional注解以声明式的方式进行事务的定制,使用非常便捷

这个注解的属性主要有:

@Transactional( 
propagation = Propagation.REQUIRED, 
isolation = Isolation.DEFAULT, 
readOnly = false, 
rollbackFor = Exception.class )

propagation是用来定制事务的传播机制的,传播难以理解,就是用来定制事务和事务之间的影响是以哪种方式进行的(前面说到多个事务可以同时运行)

下面例举一下REQUIRED,这也是这个注解属性的默认值,表示如果当前存在事务,则加入该事务;如果没有事务,则创建一个新事务。假如有两个方法A和B:

@Service
public class MyService {

    @Autowired
    private MyRepository repository;

    @Transactional
    public void methodA() {
        // 这里是方法a的事务

        // 调用方法b
        methodB();

        // 这里的操作也属于方法a的事务
    }

    public void methodB() {
        // 这里的操作也属于方法a的事务
    }
}

我们只在a方法上使用了注解,但是我们在a方法里面调用了b方法,那么按照REQUIRED的传播机制,b方法会直接加入到a方法的事务中,这样在后面我们写事务回滚的时候,b方法抛出异常同样会使得整个事务回滚,这样就可以确保业务执行要么成功要么失败

第二个属性是isolation,这个属性是用来定制事务的隔离级别的,隔离级别就那几种,读取未提交,读取已提交,可重复读,序列化

第三个属性是timeout,表示事务运行多久,单位是秒,默认值为-1,表示不限制运行时间,如果设置了timeout,超过设置的时间还没有结束事务,那么事务会进行回滚。

第四个属性是readOnly,true/false,表示事务是否为只读

第五个属性是rollbackFor,是一个对象,表示遇到什么样的异常回滚。noRollbackFor则表示遇到什么样的异常不回滚。

这写都是简单的事务概念和应用,后续将出一期事务隔离界别内容。