1. 事务的定义
概念上的定义:访问并可能更新数据库中各种数据项的一个程序执行单元
数据库里的定义:为单个逻辑单元执行的一系列操作
共同点:这些操作/方法要么全部成功,要么全部失败。
2. 事务的传播
事务的传播要从它的特点:要么全部成功,要么全部失败说起
事务传播行为用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法的时事务如何传播.
代码如下
public void methodA(){
methodB();
//doSomething
}
@Transaction(Propagation=XXX)
public void methodB(){
//doSomething
}
代码中methodA()
方法嵌套调用了methodB()
方法,methodB()
的事务传播行为由@Transaction(Propagation=XXX)
设置决定。这里需要注意的是methodA()
并没有开启事务,某一个事务传播行为修饰的方法并不是必须要在开启事务的外围方法中调用。
3. Spring里事务的传播
spring中定义了七种事务的传播行为:
public enum Propagation {
REQUIRED(0),
SUPPORTS(1),
MANDATORY(2),
REQUIRES_NEW(3),
NOT_SUPPORTED(4),
NEVER(5),
NESTED(6);
}
对应的解释也非常容易理解
REQUIRED | 如果当前没有事务,就新建一个事务,如果已经存在一个事务中,加入到这个事务中。此用法最多 |
SUPPORTS | 当前有事务则加入,如果当前没有事务,就以非事务方式执行。 |
MANDATORY | 永远加入当前的事务,如果当前没有事务,就抛出异常 |
REQUIRES_NEW | 永远新建事务,如果当前存在事务,把当前事务挂起 |
NOT_SUPPORTED | 以非事务方式执行,如果当前存在事务,就把当前事务挂起 |
NEVER | 以非事务方式执行,如果当前存在事务,则抛出异常 |
NESTED | 如果当前存在事务,则在嵌套事务内执行,所谓嵌套事务可理解为当前事务的一个子事务。如果当前没有事务,执行REQUIRED |
(此处参考博客:https://segmentfault.com/a/1190000013341344#articleHeader2 , 侵删。)
4.事务的隔离级别
要搞清楚事务的隔离级别首先要明白,在数据并发操作中,可能存在的不确定情况。
- 更新丢失。后一条记录更新冲掉了前一条
- 脏读。无效数据的读出。a线程修改某值,b线程读取该值,a线程回滚
- 不可重复读。一个事务范围内,两个相同查询返回了不同的数据值。这是由于在查询间隔,被另一个事务修改并提交了。
- 幻读。是指当事务不是独立执行时发生的一种现象,例如第一个事务对一个表中的数据进行了修改,这种修改涉及到表中的全部数据行。同时,第二个事务也修改这个表中的数据,这种修改是向表中插入一行新数据。那么,以后就会发生操作第一个事务的用户发现表中还有没有修改的数据行,就好象发生了幻觉一样。
为解决上述问题,sql规范定义了4个事务隔离级别。这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题
√: 可能出现 ×: 不会出现
脏读 | 不可重复读 | 幻读 | |
Read uncommitted | √ | √ | √ |
Read committed | × | √ | √ |
Repeatable read | × | × | √ |
Serializable | × | × | × |