spring的事务处理

By 江心秋月

spring的事务处理

spring 官方文档

https://docs.spring.io/spring-boot/docs/1.5.9.RELEASE/reference/htmlsingle/
https://docs.spring.io/spring/docs/4.3.13.RELEASE/spring-framework-reference/htmlsingle/

什么是事务(Transaction)

事务,就是一组操作数据库的动作集合。事务是现代数据库理论中的核心概念之一。
如果一组处理步骤或者全部发生或者一步也不执行,我们称该组处理步骤为一个事务。
当所有的步骤像一个操作一样被完整地执行,我们称该事务被提交。
由于其中的一部分或多步执行失败,导致没有步骤被提交,则事务必须回滚到最初的系统状态。

事务特性(4种):

  • 原子性 (atomicity):强调事务的不可分割.
  • 一致性 (consistency):事务的执行的前后数据的完整性保持一致.
  • 隔离性 (isolation):一个事务执行的过程中,不应该受到其他事务的干扰
  • 持久性(durability) :事务一旦结束,数据就持久到数据库

spring七个事务传播属性:

  1. PROPAGATION_REQUIRED – 支持当前事务,如果当前没有事务,就新建一个事务。这是最常见的选择。

  2. PROPAGATION_SUPPORTS – 支持当前事务,如果当前没有事务,就以非事务方式执行。

  3. PROPAGATION_MANDATORY – 支持当前事务,如果当前没有事务,就抛出异常。

  4. PROPAGATION_REQUIRES_NEW – 新建事务,如果当前存在事务,把当前事务挂起。

  5. PROPAGATION_NOT_SUPPORTED – 以非事务方式执行操作,如果当前存在事务,就把当前事务挂起。

  6. PROPAGATION_NEVER – 以非事务方式执行,如果当前存在事务,则抛出异常。

  7. PROPAGATION_NESTED – 如果当前存在事务,则在嵌套事务内执行。如果当前没有事务,则进行与PROPAGATION_REQUIRED类似的操作。

常用的两个事务传播属性是1和4,即PROPAGATION_REQUIRED,PROPAGATION_REQUIRES_NEW

五个隔离级别:

  • ISOLATION_DEFAULT - 这是一个PlatfromTransactionManager默认的隔离级别,使用数据库默认的事务隔离级别.
  • ISOLATION_READ_UNCOMMITTED - 这是事务最低的隔离级别,它充许别外一个事务可以看到这个事务未提交的数据。这种隔离级别会产生脏读,不可重复读和幻像读。

  • ISOLATION_READ_COMMITTED - 保证一个事务修改的数据提交后才能被另外一个事务读取。另外一个事务不能读取该事务未提交的数据。这种事务隔离级别可以避免脏读出现,但是可能会出现不可重复读和幻像读。

  • ISOLATION_REPEATABLE_READ - 这种事务隔离级别可以防止脏读,不可重复读。但是可能出现幻像读。它除了保证一个事务不能读取另一个事务未提交的数据外,还保证了避免下面的情况产生(不可重复读)。

  • ISOLATION_SERIALIZABLE - 这是花费最高代价但是最可靠的事务隔离级别。事务被处理为顺序执行。除了防止脏读,不可重复读外,还避免了幻像读。

关键词:

  1. 幻读:事务1读取记录时事务2增加了记录并提交,事务1再次读取时可以看到事务2新增的记录;
  2. 不可重复读取:事务1读取记录时,事务2更新了记录并提交,事务1再次读取时可以看到事务2修改后的记录;
  3. 脏读:事务1更新了记录,但没有提交,事务2读取了更新后的行,然后事务T1回滚,现在T2读取无效。

脏读:指一个事务读取了一个未提交事务的数据

不可重复读:在一个事务内读取表中的某一行数据,多次读取结果不同.一个事务读取到了另一个事务提交后的数据.

虚读(幻读):在一个事务内读取了别的事务插入的数据,导致前后读取不一致(insert)

分布式事务的解决方案

BASE理论

  • Basically Available(基本可用)
  • Soft state(软状态)
  • Eventually consistent(最终一致性)

    BASE理论是对CAP中的一致性和可用性进行一个权衡的结果,理论的核心思想就是:我们无法做到强一致,但每个应用都可以根据自身的业务特点,采用适当的方式来使系统达到最终一致性(Eventual consistency)。

CAP(帽子理论)

  • C:Consistency,一致性, 数据一致更新,所有数据变动都是同步的
  • A:Availability,可用性, 好的响应性能,完全的可用性指的是在任何故障模型下,服务都会在有限的时间处理响应
  • P:Partition tolerance,分区容错性,可靠性

    帽子理论证明,任何分布式系统只可同时满足二点,没法三者兼顾。关系型数据库由于关系型数据库是单节点的,因此,不具有分区容错性,但是具有一致性和可用性,而分布式的服务化系统都需要满足分区容错性,那么我们必须在一致性和可用性中进行权衡,具体表现在服务化系统处理的异常请求在某一个时间段内可能是不完全的,但是经过自动的或者手工的补偿后,达到了最终的一致性。

https://github.com/codingapi/tx-lcn

https://github.com/liuyangming/ByteTCC

两阶段提交(基于XA协议的两阶段提交方案)

  1. 第一阶段,所有事务参与者将执行结果的成功与否反馈给事务协调者,但是不提交。

  2. 第二阶段,事务协调者根据返回的结果,决定是全部提交,还是全部不提交。

可能子事务B在执行时,要访问还未提交事务的子事务A锁定的资源,导致锁等待,吞吐量会遇到瓶颈,导致性能不高。

TCC编程模式(Try/Confirm/Cancel)

所谓的TCC编程模式,也是两阶段提交的一个变种。TCC提供了一个编程框架,将整个业务逻辑分为三块:Try、Confirm和Cancel三个操作。

总之,TCC就是通过代码人为实现了两阶段提交,不同的业务场景所写的代码都不一样,复杂度也不一样,因此,这种模式并不能很好地被复用。

  1. Try:尝试待执行的业务

这个过程并未执行业务,只是完成所有业务的一致性检查,并预留好执行所需的全部资源

  1. Confirm:执行业务

这个过程真正开始执行业务,由于Try阶段已经完成了一致性检查,因此本过程直接执行,而不做任何检查。并且在执行的过程中,会使用到Try阶段预留的业务资源。

  1. Cancel:取消执行的业务

若业务执行失败,则进入Cancel阶段,它会释放所有占用的业务资源,并回滚Confirm阶段执行的操作。

消息事务+最终一致性(基于可靠消息服务的分布式事务)

所谓的消息事务就是基于消息中间件的两阶段提交,本质上是对消息中间件的一种特殊利用,它是将本地事务和发消息放在了一个分布式事务里,保证要么本地操作成功成功并且对外发消息成功,要么两者都失败,开源的RocketMQ就支持这一特性.

该方案采用最终一致的,牺牲了一致性,换来了性能的大幅度提升。存在造成数据不一致的风险

将本地A操作和远程B操作的消息作为一个事物,一起提交,要么都成功,要么都失败,缺点是,对业务代码的侵入性太大,实现起来复杂。

全局事务(DTP模型)

全局事务基于DTP模型实现。DTP是由X/Open组织提出的一种分布式事务模型——X/Open Distributed Transaction Processing Reference Model。它规定了要实现分布式事务,需要三种角色:

  • AP:Application 应用系统
    • 它就是我们开发的业务系统,在我们开发的过程中,可以使用资源管理器提供的事务接口来实现分布式事务。
  • TM:Transaction Manager 事务管理器
    • 分布式事务的实现由事务管理器来完成,它会提供分布式事务的操作接口供我们的业务系统调用。这些接口称为TX接口。
    • 事务管理器还管理着所有的资源管理器,通过它们提供的XA接口来同一调度这些资源管理器,以实现分布式事务。
    • DTP只是一套实现分布式事务的规范,并没有定义具体如何实现分布式事务,TM可以采用2PC、3PC、Paxos等协议实现分布式事务。
  • RM:Resource Manager 资源管理器
    • 能够提供数据服务的对象都可以是资源管理器,比如:数据库、消息中间件、缓存等。大部分场景下,数据库即为分布式事务中的资源管理器。
    • 资源管理器能够提供单数据库的事务能力,它们通过XA接口,将本数据库的提交、回滚等能力提供给事务管理器调用,以帮助事务管理器实现分布式的事务管理。
    • XA是DTP模型定义的接口,用于向事务管理器提供该资源管理器(该数据库)的提交、回滚等能力。
    • DTP只是一套实现分布式事务的规范,RM具体的实现是由数据库厂商来完成的。