DB-数据库事务及隔离级别介绍,Spring事务传播行为介绍

9 篇文章 0 订阅
1 篇文章 0 订阅

什么是事务?

事务(Transaction),在计算机术语中,指将多个单独的操作组合在一起,其中一个操作执行失败,所有执行的操作全部撤回,只有当所有操作全部执行成功,才算成功,这多个操作组合成的整体叫做事务;

例如:A给B转账100元,分两个操作,A减100元,B加100元,只有当这两个操作都执行成功,这个转账事务才算成功;如果B加100元失败,A则必须回退减100元操作。

事务的四大特性

特性描述
原子性(Atomicity)指事务是一个不可分割的单位,事务中的操作要么全部成功,要么全部失败
一致性(Consistency)事务执行前后,数据从一个一致性状态变为另一个一致性状态(数据按照预期变化)
例如:A给B转账100元事务
事务前状态:A有1000元,B有1000元;
事务后状态:A有900元,B有1100元;
隔离性(Isolation)在多个事务同时执行过程中,各个事务之间的影响;这里又分为四个隔离级别,我们后面会讲到;
例如:脏读问题
1. A发起事务1,查询账户有1000元,此时事务1未关闭;
2. B发起事务2,给A转账100元,此时事务2也未关闭;
3. A在事务1中,再次查询账户,发现有1100元,读到了事务2未提交的数据;
这是脏读问题。
持久性(Durability)指事务一旦提交成功,他对数据的改变是永久性的,接下来即使服务器崩溃关闭,也不会对数据有任何影响。

事务的隔离级别

事务并发问题

  1. 脏读:
    一个事务,读取到另一个事务未提交的数据
  2. 不可重复读:
    一个事务读取到另一个事务已经提交的Update数据(事务内前后查询同一个数据不一致)
    • 场景:
      a. A开启事务1,查询账户有1000元,未关闭事务1
      b. B开启事务2,给A转账100元,提交事务2
      c. A在事务1内再次查询账户,有1100元,和第一次查询数据不一致;
  3. 幻读(虚读):
    一个事务读取到另一个事务已经提交的InsertDelete数据(事务内前后统计同一条件数据条数不同)
    • 场景:
      a. 事务1查询员工总数有10人
      b. 事务2新增2个员工,提交事务2
      c. 事务1再次查询员工有12人

数据库定义四种隔离级别

隔离级别依次提升,数据安全性依次提高,数据库查询效率依次降低

  1. 读未提交(read-uncommitted)
    在一个事务中,可以读取其他事物未提交的数据变化;这种能读取其他事物未提交的数据变化的现象叫脏读,生产环境请勿使用
  2. 读已提交(read-committed)
    在一个事务中,可以读取其他事物已提交的数据变化;由于同一事物中两次读取可能得到不一样的结果,所以也交不可重复读。
  3. 可重复读(repeatable-read)
    Mysql的默认隔离级别,在一个事务中,可以重复读取到事务刚开始时看到的数据,并不会因为其他事物提交数据而改变,避免了脏读,不可重复读;但是他无法解决幻读问题。
  4. 串行化(serializable)
    这是最高的隔离级别,它强制事务串行执行,避免了幻读;它会在每一行数据上加锁,,多以会导致大量超时和锁争用问题。
隔离级别读数据一致性脏读不可重复的幻读
未提交读最低级别,只保证不读取物理上损坏的数据
已提交读语句级
可重复读事务级
串行化最高级别,事务级

扩展:
Mysql使用了快照读,当前读,MVCC,Next-Lock,GAP锁等思想实现了可重复读

事务的传播行为

事务的控制往往是在程序的Service层,而Service层的方法我们有时候,需要互相调用,而每个Service方法都可能有自己的事务,这时就需要事务传播行为的概念。

以下我们讲解一下Spring定义的事务传播

事务定义说明
PROPAGATION_REQUIRED如果当前没有事务,就新建一个事务,如果已经存在一个事务中, 加入到这个事务中。这是最常⻅的选择。
PROPAGATION_SUPPORTS支持当前事务,如果当前没有事务,就以非事务方式执行。
PROPAGATION_MANDATORY使用当前的事务,如果当前没有事务,就抛出异常。
PROPAGATION_REQUIRES_NEW新建事务,如果当前存在事务,把当前事务挂起。
PROPAGATION_NOT_SUPPORTED以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。
PROPAGATION_NEVER以非事务方式执行,如果当前存在事务,则抛出异常。
PROPAGATION_NESTED如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则执行与PROPAGATION_REQUIRED类似的操作。

注意:

  • PROPAGATION_REQUIRES_NEWPROPAGATION_NESTED是独立事务,但是如果被调用方法事务回滚后异常抛出,而外部方法没捕获还是会导致外部方法事务回滚;只有try_catch处理后外部方法事务才不会回滚
  • PROPAGATION_NESTED作为事务嵌套,同时兼具了required,requires_new的特性。
    • 当外层事务回滚时PROPAGATION_NESTEDPROPAGATION_REQUIRED同时内层全部进行回滚
    • 当内层事务回滚时,PROPAGATION_NESTEDPROPAGATION_REQUIRES_NEW不影响外层事务
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值