Spring事务的隔离级别详细讲解~Spring事务第二篇

Spring事务的隔离级别

为什么要事务隔离?如果没有事务隔离,当存在多个事务并发的时候,会产生更新丢失、脏读、不可重复读、幻读等问题。

一、没有事务隔离引发的问题

1、更新丢失

当两个或多个事务更新同一行记录,会产生更新丢失现象。可以分为回滚覆盖和提交覆盖。

例如:事务T1查询数据,事务T2查询数据,事务T1修改数据并提交,事务T2修改数据,此时事务T2提交或者回滚,都会导致事务T1修改的数据被覆盖。

2、脏读

脏读又称无效数据读出。一个事务读取另外一个事务还没有提交的数据。

例如,事务T1修改了一行数据,但是还没有提交,这时候事务T2读取了被事务T1修改后的数据,之后事务T1因为某种原因Rollback了,那么事务T2读取的数据就是脏的。

3、不可重复读

指在同一个事务内,对同一行数据的多次查询,返回了不同的结果。

例如,事务T1第一次查询了某行数据,然后事务T2对这行数据的某个字段做了修改,并且提交了数据。事务T1第二次查询该行数据的时候,得到了事务T2修改过的结果。

不可重复读和脏读的区别在于,脏读是读了未提交的数据,而不可重复读是读了提交了的数据。当然,不可重复读在某些情况下并不是问题,有时候我们就是要在同一事务下查询到数据的最新状态。

4、幻读

幻读又称虚读。同一条SQL语句在同一个事务中的多次查询,得到的数据量(条数)不一样。

例如,事务T1对一个表中所有的行的某个数据项做了从“1”修改为“2”的操作,这时事务T2又对这个表中插入了一行数据项,而这个数据项的数值还是为“1”并且提交给数据库。而操作事务T1的用户如果再查看刚刚修改的数据,会发现还有一行没有修改,其实这行是从事务T2中添加的,就好像产生幻觉一样,这就是发生了幻读。

二、用事务的隔离级别进行解决

隔离级别的用法

@Transactional注解通过isolation属性设置事务隔离级别

@Transactional(isolation=Isolation.DEFAULT)
public void methodA(){
    
    
// 业务逻辑 
// 操作数据库
}

三、isolation属性的值有以下5种

1、DEFAULT

这是默认值,表示跟连接的数据库设置的隔离级别一致。

2、READ_UNCOMMITTED

读未提交(会出现脏读, 不可重复读,幻读) 基本不使用

以操作同一行数据为前提,读事务允许其他读事务和写事务,未提交的写事务禁止其他写事务,但允许其他读事务。此隔离级别可以防止更新丢失,但不能防止脏读、不可重复读、幻读。此隔离级别可以通过“排他写锁”实现。

3、READ_COMMITTED

读已提交(会出现不可重复读和幻读)

以操作同一行数据为前提,读事务允许其他读事务和写事务,未提交的写事务禁止其他读事务和写事务。此隔离级别可以防止更新丢失、脏读,但不能防止不可重复读、幻读。此隔离级别可以通过“瞬间共享读锁”和“排他写锁”实现。

4、REPEATABLE_READ

可重复读(会出现幻读)

以操作同一行数据为前提,读事务禁止其他写事务(但允许其他读事务),未提交的写事务禁止其他读事务和写事务。此隔离级别可以防止更新丢失、脏读、不可重复读,但不能防止幻读。此隔离级别可以通过“共享读锁”和“排他写锁”实现。

5、SERIALIZABLE

可串行化

提供严格的事务隔离。它要求事务序列化执行,事务只能一个接着一个地执行,不能并发执行。此隔离级别可以防止更新丢失、脏读、不可重复读、幻读。如果仅仅通过“行级锁”是无法实现事务序列化的,必须通过其他机制保证新插入的数据不会被刚执行查询操作的事务访问到。这种事务隔离级别效率低下,比较耗数据库性能,一般不使用。

四、扩展:

1、常见数据库的默认事务隔离级别

Oracle,Sql Server的默认隔离级别是 READ_COMMITTED,
Mysql的默认隔离级别是 REPEATABLE_READ。

2、隔离级别的设置只对当前连接有效

对于使用Mysql命令窗口而言,一个窗口就相当于一个连接,当前窗口设置的隔离级别只对当前窗口中的事务有效;对于JDBC操作数据库来说,一个Connection对象相当于一个链接,而对于Connection对象设置的隔离级别只对Connection对象有效,与其他链接Connection对象无关。

3、设置数据库的隔离级别一定要是在开启事务之前

mybatis中的事务:
它是通过sqlSession对象的commit方法和rollback方法实现事务的提交和回滚。

4、隔离级别常见sql设置

查看当前事务隔离级别:select @@transaction_isolation;
设置当前会话的事务隔离级别: set session transaction isolation level XXX(隔离级别);
设置当前全局的事务隔离级别: set global transaction isolation level XXX(隔离级别);

猜你喜欢

转载自blog.csdn.net/qq_42547733/article/details/128705149