数据库的事务隔离级别和传播属性
事务隔离级别定义:一个事务对数据库的修改与并行的另一个事务的隔离程度。
2个并发事务同时访问数据库表相同的行时,可能存在以下三个问题:
1 幻想读
事务1读取一条指定where条件的语句,返回结果集。此时事务2插入一行新纪录,恰好满足事务1的where条件。然后事务1使用相同的条件再次查询,结果集中可以看到事务2插入的记录,这条新纪录就是幻读。
2 不可重复读
事务1读取一行记录,紧接着事务2修改了事务1刚刚读取的记录,然后事务1再次查询,发现与第一次读取的记录不同,这称为不可重复读。
3 脏读
事务1更新了一行记录,还未提交所做的修改,这个事务2读取了更新后的数据,然后事务1执行回滚操作,取消刚才的修改,所以事务2所读取的行就无效,也就是脏数据。为了解决这些问题,SQL标准定义了4中事务隔离级别
read uncommited 读未提交
read commited 读提交 可以避免脏读
repeatable read 可重复读 可以避免脏读、不可重复读
serializable 串行化 可以避免脏读、不可重复读、幻读 是数据库事务的最高级别
Oracle、SQL Server : 默认事务的隔离级别 read committed
MySQL: 默认事务的隔离级别 repeatable read
set transaction isolation level { read uncommited | read commited |repeatable read|serializable }
Spring框架中提供了注解@Transactional,它可以定义事务的传播属性(propagation)和隔离级别(isolation )
jpa的@Transactional
Spring的事务的传播属性(propagation),事务的传播是指事务的嵌套的时候,它们的事务属性。
required 默认的属性
如果存在一个事务,则支持当前事务。如果没有事务则开启一个新的事务。被设置成这个级别时,会为每一个被调用的方法创建一个逻辑事务域。如果前面的方法已经创建了事务,那么后面的方法支持当前的事务,如果当前没有事务会重新建立事务。
mandatory
支持当前事务,如果当前没有事务则抛出异常。
never
以非事务方式执行,如果当前存在事务,则抛出异常。
not supported
以非事务方式执行,如果当前存在事务,就把当前事务挂起。
requires new
新建事务,如果当前存在事务,把当前事务挂起。
supports
支持当前事务,如果当前没有事务,就以非事务方式执行
nested
支持当前事务,新增安全点,与当前事务同步提交或回滚。嵌套事务一个非常重要的概念就是内层事务依赖于外层事务。外层事务失败时,会回滚内层事务所做的动作。而内层事务操作失败并不会引起外层事务的回滚。
propagation nested与propagation requires new的区别
它们非常 类似,都像一个嵌套事务,如果不存在一个活动的事务,都会开启一个新的事务。使用PROPAGATION_REQUIRES_NEW时,内层事务与外层事务就像两个独立的事务一样,一旦内层事务进行了提交后,外层事务不能对其进行回滚。两个事务互不影响。两个事务不是一个真正的嵌套事务。同时它需要JTA 事务管理器的支持。 使用PROPAGATION_NESTED时,外层事务的回滚可以引起内层事务的回滚。而内层事务的异常并不会导致外层事务的回滚,它是一个真正的嵌套事务。
参考资料
1@Transactional必知必会 https://www.jianshu.com/p/5687e2a38fbc
2 Spring事务传播属性和隔离级别 https://www.cnblogs.com/jimmy-muyuan/p/5722708.html
3 ORACLE数据库事务隔离级别 https://www.cnblogs.com/jackal/archive/2011/02/14/1954231.html
领取专属 10元无门槛券
私享最新 技术干货