springboot事务处理


事务隔离级别

事务隔离性的4个级别,
1、读未提交(Read Uncommitted)
读未提交是数据库应保证的最低的隔离性级别:事务中的修改,即使没有提交,对其他事务也都是可见的。
读未提交面临脏读的问题:事务可以读取未提交的数据,而该数据可能在未来因回滚而消失。从性能上来说,读未提交不会比其他的级别好太多,但却缺乏其他级别的很多好处。除非真的有非常必要的理由,在实际应用中很少使用。
2、读已提交(Read Committed)
读已提交满足前面提到的隔离性的简单定义:一个事务所做的修改在最终提交以前,对其他事务是不可见的。换句话说,一旦提交,该事务所作的修改对其他正在进行中的事务就是可见的。
狭义上,读已提交解决了脏读的问题。这个级别有时候叫做不可重复读,面临不可重复读的问题:两次执行同样的查询,如果第二次读到了其他事务提交的结果,则会得到不一样的结果。

	大多数数据库的默认隔离级别都是Read Committed,但MySQL不是。

3、可重复读(Repeatable Read)
在读已提交的基础上,可重复读解决了部分不可重复的问题:同一个事务中多次读取同样记录结果是一致的。记录指具体的数据行。

未能解决的那部分称为幻读:当某个事务在读取目标范围内的记录时,另一个事务又在该范围内插入了新的记录,当之前的事务再次读取该范围的记录时,会产生第一次读取范围时不存在的幻行(Phantom Row)。需要注意的是,只有插入会产生幻行。

MySQL的默认隔离级别是可重复读,有幻读问题。

4、可序列化(Serializable);
可序列化是最高的隔离级别:强制事务序列化执行。
可序列化解决了幻读问题。简单来说,可序列化会在目标范围加独占锁,将并发读写相同范围数据的请求序列化。可序列化会导致大量的超时和锁争用问题,因此,实际应用中很少用到这个隔离级别,只有在非常需要确保数据的一致性而且可以接受没有并发的情况下,才考虑采用该级别。


一、事务原理

基于锁的并发控制中,4种隔离性级别的实现原理。重点关注读锁(read lock,或称共享锁)、写锁(write lock,或称排它锁)、范围锁(range lock)、锁的持有时间等概念。
读锁又称为共享锁,共享锁就是多个事务共享一把锁,都能访问到数据,但都只能读不能修改。
写锁又称为排他锁,排他锁和其他事务不能共存,如果一个事务获取了一个数据行的排他锁,其他的事务不可以再获取到该数据行的任何锁,获取到排他锁的数据行可以对行进行读取和修改,没有获取到锁的数据行 不能 读取和修改。
mysql的innoDB引擎默认修改的语句都会加上排他锁,比如update insert delete
范围锁针对目标范围,一般是指sql语句中where约束的范围

二、使springboot事务处理

1、事务隔离级别

在这里插入图片描述
我们可以看org.springframework.transaction.annotation.Isolation枚举类中定义了五个表示隔离级别的值:

public enum Isolation {
    DEFAULT(-1),
    READ_UNCOMMITTED(1),
    READ_COMMITTED(2),
    REPEATABLE_READ(4),
    SERIALIZABLE(8);
}
1、DEFAULT:这是默认值,表示使用底层数据库的默认隔离级别。对大部分数据库而言,通常这值就是:READ_COMMITTED。
2、READ_UNCOMMITTED:该隔离级别表示一个事务可以读取另一个事务修改但还没有提交的数据。该级别不能防止脏读和不可重复读,因此很少使用该隔离级别。
3、READ_COMMITTED:该隔离级别表示一个事务只能读取另一个事务已经提交的数据。该级别可以防止脏读,这也是大多数情况下的推荐值。
4、REPEATABLE_READ:该隔离级别表示一个事务在整个过程中可以多次重复执行某个查询,并且每次返回的记录都相同。即使在多次查询之间有新增的数据满足该查询,这些新增的记录也会被忽略。该级别可以防止脏读和不可重复读。
5、SERIALIZABLE:所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。

2、事务传播

所谓事务的传播行为是指,如果在开始当前事务之前,一个事务上下文已经存在,此时有若干选项可以指定一个事务性方法的执行行为。

我们可以看org.springframework.transaction.annotation.Propagation枚举类中定义了6个表示传播行为的枚举值:

public enum Propagation {
    REQUIRED(0),
    SUPPORTS(1),
    MANDATORY(2),
    REQUIRES_NEW(3),
    NOT_SUPPORTED(4),
    NEVER(5),
    NESTED(6);
}
1、REQUIRED:如果当前存在事务,则加入该事务;如果当前没有事务,则创建一个新的事务。默认类型
2、SUPPORTS:如果当前存在事务,则加入该事务;如果当前没有事务,则以非事务的方式继续运行。
3、MANDATORY:如果当前存在事务,则加入该事务;如果当前没有事务,则抛出异常。
4、REQUIRES_NEW:创建一个新的事务,如果当前存在事务,则把当前事务挂起。
5、NOT_SUPPORTED:以非事务方式运行,如果当前存在事务,则把当前事务挂起。
6、NEVER:以非事务方式运行,如果当前存在事务,则抛出异常。
7、NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于REQUIRED。

指定方法:通过使用propagation属性设置,例如:
@Transactional(propagation = Propagation.REQUIRED)
已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页