你必须搞懂的数据库的事务隔离级别和传播属性

数据库的事务隔离级别和传播属性

事务隔离级别定义:一个事务对数据库的修改与并行的另一个事务的隔离程度

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

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20180717G1PT0G00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码关注云+社区

领取腾讯云代金券