Spring事务杂谈
1. 什么是事务
事务就是以一种可控的方式,对资源进行的一组操作,保证了资源在事务前后,始终应处于被期待的正确的状态。比如不会受到宕机等原因的影响。事务本身,具有如下4种属性-ACID。(所以说事务是酸的ww)
原子性(A)
原子性的描述很简单,就是要么都做,要么都别做。比如转账业务,A向B转100元。首先要从A账户扣掉100,再给B的账户加上100,可能中间会出现问题,只扣A的了没给B加上,这时候就需要原子性来保证了。
一致性(C)
一致性的定义好多,我认为一致性主要是事务前后能通过一致性检查。比如转账前AB的钱总数,和转账后AB钱的总数,是不能变的。
隔离性(I)
隔离性主要指定的是事务并发执行时候的一些要求。
首先说下事务在并发条件下存在的问题。
脏读
事务甲读到了事务乙还没提交的修改。假设这个事务乙回滚了,那么事务甲读的就是脏数据,所以叫做脏读。
不可重复读
事务甲做了如下操作,读取A——干点其他事——读取A。这时候,事务乙,悄悄的提交了对A的修改。事务甲发现,两次读到的行不一样啊。因为重复读取时,数据变了,所以叫做不可重复读。
幻读
事务甲做了如下操作,按A条件查询结果集合——干点其他事——按A条件查询结果集合。事务乙,悄悄地在甲干其他事时,插入了一行符合查询条件A的数据。甲发现,第二次怎么比第一次多了一条啊。所以幻读的定义就是,同样一个事务,查询多次结果集合,结果是不同的,称为幻读,因为就像幻觉一样,数据突然变多了或变少了。
那么,如何解决这些问题呢?设计数据库的大佬们通过定义了4种不同的隔离级别,以解决这种问题。
未提交读
一个事务,可以在事务对数据进行更新,在它还没有提交时,另一个事务就可以看到这个数据。
已提交读
一个事务的更新操作,只有在提交后,另一个事务才能读到更新后的数据。这也就是解决了脏读的问题。
可重复读
保证了同一个事务,对同一数据多次查询,结果总是相同的。看名字就知道解决了不可重复读的问题。
可串行化
所有的事物,必须按照一定顺序串行执行。解决了幻读,因为串行了,所以自然所有设计到并发数据不一致的问题就解决了。
MySQL InnoDB的默认级别,是可重复读。因为事务隔离性要求越高,实现时加锁粒度越大,系统并发度越低,所以MySQL采用了可重复读这个级别。
持久性(D)
事务的持久性是说,一旦事务成功提交,更改就要被永远铭记,不能再逆转。
2. 角色与事务
一个事务中,通常会有如下几个参与者。
RM:负责储存管理系统数据库的资源状态
TPM:负责分布式场景(多个RM),情况下的协调工作。
TM:TPM的核心模块,通常采用两阶段提交方法保证分布式事务的执行。
具体如下图所示。