事务相关

167 阅读8分钟

Spring的事务传播机制:7种

  • REQUIRED(默认)

  • 如果当前没有事务,就新建一个事务,如果已经有事务,就加入到这个事务

  • SUPPORTS

  • 支持当前事务,如果当前没有事务,就以非事务方式执行

  • MANDATORY

  • 使用当前的事务,如果当前没有事务,就抛出异常(父方法必须有事务)

  • REQUIRES_NEW

  • 新建事务,如果当前存在事务,就挂起当前事务。

  • 独立提交事务,不受调用者事务影响,父级异常,也正常提交

  • NOT_SUPPORTED

  • 已非事务方式执行,如果当前存在事务,则把当前事务挂起

  • NEVER

  • 以非事务方式执行,如果当前存在事务,就抛出异常(父方法必须无事务)

  • **NESTED
    **

  • 如果当前存在事务,它将成为父级事务的一个子事务,方法结束并没有提交,等到父事务结束才提交

  • 如果当前没有事务,则新建事务

  • 如果它异常,父级可捕获异常不会滚,正常提交

  • 如果父级异常,它必然回滚(与REQUIRES_NEW的区别****)****

事务可以看做是一次大的活动,它由不同的小活动组成,这些活动要么全部成功,要么全部失败.

脏读:一个事物正在访问数据,并且对数据进行了修改,此时还没有提交,这时另一个事务访问了该数据,然后使用了这个数据

**不可重复读:重点在修改。**一个事物之内,多次读取统一数据。一个事务没有结束的时候,另一个事务也在访问改数据,在第一个事务两次读取数据之间,由于第二个事务的修改,两次读取到的数据不一致。

**幻读:重点在新增或者删除。**事务不是独立执行时发生的,比如第一个事务访问了范围内数据,同时,第二个事务对这个表中的数据进行了插入操作,第一个事务就会发现前后读取的数据不一致,就好像发生了幻觉一样。

数据库事务的四种隔离级别:

写读是脏读,读写读是不可重复读,whereinsertwhere是幻读

  • 读未提交(Read UnCommitted)

  • 可以读到未提交的内容

  • 在这个级别下,查询是不会加锁的,可能会产生 脏读,不可重复读,幻读

  • 读已提交(Read Committed)最常用(SQL Server、Oracle)

  • 只能读到已经提交的内容

  • 可防止脏读

  • 可重复度(Repeated Read)Mysql的默认隔离级别

  • 针对“不可重复读”设置的隔离级别

  • 当前事务中如果不发生修改,那么事务前后读取到的数据是一样的,且不会读取到其他事务未提交或者已提交的数据。读事务禁止写事务,写事务禁止读和写事务。

  • 可防止脏读和不可重复读

  • 串行化(Serializeble)

  • 数据库最高的隔离级别,事务只能串行化顺序执行,一个一个排队执行

  • 脏读,不可重复读,幻读都可以避免,但是执行效率奇差,性能开销大

数据库事务的四大特性:

  • A (Atomic): 原子性,构成事务的所有操作,要么都执行完成,要么全部不执行,不可能出现部分成功部分失败的情况。

  • C(consistency): 一致性,事务开始前和结束后,数据库的完整性约束没有被破 坏。比如A向B转账,不可能A扣了钱B却没有收到。

  • I(Isolation):隔离性,隔离性指不同的事务之间相互不干扰。

  • D(Durability):事务完成后,对数据的修改将会持久化到数据库中。

分布式事务:分布式环境下不同服务之间通过网络协助完成事务称为分布式事务

分布式事务产生场景:

  1. 微服务架构,跨JVM进程产生分布式事务
  2. 单体系统访问多个数据库实例,跨数据库实产生分布式事务
  3. 多服务访问同一个数据库实例

CAP理论:

所有分布式场景中不会同时具备CAP三个特性,因为在具备了P的前提下,C和A是不能共存的

  • C(Consistency)一致性
  • A(Availability)可用性
  • P(Partition tolerance)分区容错性,分布式系统具备的基本能力。

BASE理论:对CAP理论的延伸

  • Basically Available(基本可用),系统出现故障时,允许损失部分可用功能,保证核心功能可用

  • Soft State(软状态),允许系统中的数据存在中间状态(软状态),允许系统数据同步存在延迟

  • Eventually Consistency(最终一致性),经过一段时间后,所有节点的数据都能达到一致

分布式事务解决方案

  • 2PC
  • TCC
  • 可靠消息最终一致性
  • 最大努力通知

1.2PC:

  • 准备阶段(Prepare phase) 事务管理器给每个参与者发送Prepare消息,每个事务参与者在本地执行事务,并写本地的Redo/Undo日志,此时事务并没有提交

  • 提交阶段(Commit phase) 事务管理器收到了参与者执行失败或者超时的消息时,直接给每个参与者发送回滚消息,否则发送提交消息。事务参与者根据事务管理器的指令执行提交或者回滚操作,并释放事务处理中使用的锁资源。注意,必须在最后阶段释放锁资源。

  • ****基于数据库的XA协议来实现2PC,****数据库提供2PC接口协议,Oracle,Mysql都支持两阶段提交协议。涉及到三个角色,AP、 RM、TM,即应用程序、资源管理器、事务管理器

  • 需要本地数据库支持XA协议

  • 资源锁需要等到两个结束才释放,性能较差

  • ****Seata方案,阿里的开源的分布式解决方案,****seata把全局事务理解成了包含若干分支事务的全局事务,工作在应用层,通过协调本地数据库的分支事务来完成全局事务。性能较好,对业务0侵入。

  • TC(Transaction Coordinator)事务协调器,独立的中间件,需要独立运行,维护全局事务的运行状态。接收TM的的指令发起全局事务的提交和回滚负责与RM通信协调各个分支事务的提交和回滚。

  • TM(Transaction Manager)事务管理器,TM需要嵌入到程序中(Jar包),负责开启一个全局事务,并向TC发起全局提交或全局回滚的指令。

  • RM(Resource Manager),控制分支事务,接收TC的指令,驱动本地事务的提交或回滚。

2. TCC(Try  Confirm  Cancel)

  • Try 预处理,资源预留。Try执成功,执行Confirm。Try执行失败,执行Cancel。

  • Confirm 确认提交

  • Cancel  需要回滚的状态下,执行分支事务的业务取消。

  • 基于Hmily的TCC解决方案(轻量级)利用AOP对本地方法进行拦截处理,并记录日志。只需要暴露Try接口

  • 需要注意三种异常;

  • 没有调用Try,就调用的Cancel回滚 解决方案:插入执行记录

  • 幂等  解决方案:插入执行记录

  • 悬挂 Cancel比Try先执行   解决方案:执行一阶段时判断二阶段是否已经执行

3.可靠消息最终一致性:

事务发起方执行完本地事务后发送一条消息,事务参与方一定能够接受消息并处理事务成功。

需解决这几个问题:

  1. 本地事务和消息发送的原子性(可通过MQ的事务消息解决)
  2. 事务接收方接收消息的可靠性,接收不到可重复接受
  3. 消息重复消费(幂等性)
  • 本地消息表方案,定时扫描消息表,发送给MQ

  • 基于RocketMQ

  • 支持事务消息

4.最大努力通知:

  • 有一定的消息重复通知机制。

  • 接收通知方没有接受到通知,要有一定的机制对消息重复通知

  • 消息校对机制。

  • 如果尽最大努力也没有通知到接收方,或者接收方想要再次消费消息,可由接收方通过通知放主动查询消息来满足需求

最大努力通知和可靠消息最终一致性的区别:

  1. 解决方案思想不同:

  2. 可靠消息最终一致性,消息发起方要保证将消息发出去,并且发送到消息接收方,消息的可靠性有发起方保证(比如事务消息)

  3. 最大努力通知,消息发起方将业务结果尽最大努力通知给消息接收方,但是如果接收方接收不到,此时需要接收方主动调用发起方的业务查询接口,通知的可靠性由接收方保证

  4. 业务场景不同

  5. 可靠消息最终一致性关注的是交易过程的一致性,以异步的方式完成交易。

  6. 最大努力通知关注的是交易后的事务结果,将结果可靠的通知出去

  7. 技术解决方向不同

  8. 可靠消息最终一致性要解决消息从发出到接收的一致性

  9. 最大努力通知只提供消息接收的可靠性