单机事务
事务的特性
ACID
- A(Atomicity),原子性。指事务中的语句要么全都执行,要么全都不执行。
- C(Consistency),一致性。指事务执行前后数据库中数据的一致性不发生改变。
- I(Isolation),隔离性。指事物之间相互隔离,操作独立,不会互相影响。
- D(Durability),持久性。值事务对数据库的更改是持久的,不会无缘无故的回滚。
事务的隔离级别
由低到高
-
Read-Uncommited,读未提交。
-
Read-Commited,读已提交。
-
Read-Repeatable,可重复读。
-
Serializable,串行化。
Spring中事务的传播行为
传播行为 意义 PROPERGATION_MANDATORY 表示方法必须运行在一个事务中,如果当前事务不存在,就抛出异常 PROPAGATION_NESTED 表示如果当前事务存在,则方法应该运行在一个嵌套事务中。否则,它看起来和PROPAGATION_REQUIRED 看起来没什么俩样 PROPAGATION_NEVER 表示方法不能运行在一个事务中,否则抛出异常 PROPAGATION_NOT_SUPPORTED 表示方法不能运行在一个事务中,如果当前存在一个事务,则该方法将被挂起 PROPAGATION_REQUIRED 表示当前方法必须运行在一个事务中,如果当前存在一个事务,那么该方法运行在这个事务中,否则,将创建一个新的事务 PROPAGATION_REQUIRES_NEW 表示当前方法必须运行在自己的事务中,如果当前存在一个事务,那么这个事务将在该方法运行期间被挂起 PROPAGATION_SUPPORTS 表示当前方法不需要运行在一个是事务中,但如果有一个事务已经存在,该方法也可以运行在这个事务中
分布式事务
分布式事务是指会涉及到操作多个数据库的事务,在分布式系统中,各个节点之间在物理上相互独立,通过网络进行沟通和协调。
XA 是指由 X/Open 组织提出的分布式事务处理的规范。
两阶段提交(2PC)
二阶段提交 (Two-phaseCommit) 是指, 为了使基于分布式系统架构下的所有节点在进行事务提交时保持一致性而设计的一种算法(Algorithm),也被称为是一种协议(Protocol)。在分布式系统中,每个节点虽然可以知晓自己的操作时成功或者失败,却无法知道其他节点的操作的成功或失败。当一个事务跨越多个节点时,为了保持事务的 ACID 特性, 需要引入一个作为协调者的组件来统一掌控所有节点(称作参与者)的操作结果并最终指示这些节点是否要把操作结果进行真正的提交(比如将更新后的数据写入磁盘等等)。
因此,二阶段提交的算法思路可以概括为:参与者
将操作成败通知协调者
,再由协调者
根据所有参与者
的反馈情报决定各参与者
是否要提交操作还是中止操作。
准备阶段
事务协调者(事务管理器)给每个参与者(资源管理器)发送 Prepare
消息,每个参与者要么直接返回失败(如权限验证失败),要么在本地执行事务, 写本地的 redo 和 undo 日志,但不提交
,到达一种“万事俱备,只欠东风”的状态。
提交阶段
如果事务协调者收到了参与者的失败消息,直接给每个参与者发送回滚(Rollback)消息;否则,发送提交(Commit)消息;参与者根据协调者的指令执行提交或者回滚操作,释放所有事务处理过程中使用的锁资源。
缺点:
-
同步阻塞
执行过程中,所有参与节点都是事务阻塞型的。当参与者占有公共资源时,其他第三方节点访问公共资源不得不处于阻塞状态。
-
单点故障
由于协调者的重要性,一旦协调者发生故障。参与者会一直阻塞下去。尤其在提交阶段,协调者发生故障,那么所有的参与者还都处于锁定事务资源的状态中,而无法继续完成事务操作。(如果是协调者挂掉,可以重新选举一个协调者,但是无法解决因为协调者宕机导致的参与者处于阻塞状态的问题)
-
数据不一致
在提交阶段中,当协调者向参与者发送
commit
请求之后,发生了局部网络异常或者在发送commit
请求过程中协调者发生了故障,导致只有一部分参与者接受到了commit
请求。而在这部分参与者接到commit
请求之后就会执行commit
操作。但是其他部分未接到commit
请求的参与者则无法执行事务提交。于是整个分布式系统便出现了数据不一致性的现象。 -
事务状态不确定
协调者再发出
commit
消息之后宕机, 而唯一
接收到这条消息的参与者同时也宕机了。那么即使协调者通过选举协议产生了新的协调者, 这条事务的状态也是不确定的,无法知道事务是否已经提交。
三阶段提交(3PC)
三阶段提交( Three-phase commit ) ,是二阶段提交(2PC)的改进版本。
与 2PC 不同之处在于:
- 引入超时机制。同时在协调者和参与者中都引入超时机制。
- 在第一阶段和第二阶段中增加了一个准备阶段。保证了在最后提交阶段之前各参与节点的状态是一致的。也就是说,除了引入超时机制之外, 3PC 把 2PC 的准备阶段再次一分为二,这样三阶段提交就有
CanCommit
、PreCommit
、DoCommit
三个阶段。
CanCommit 阶段
协调者向所有参与者发送 CanCommit
请求,参与者如果可以提交就返回 Yes
响应,否则返回 No
响应。
PreCommit 阶段
协调者根据参与者的响应情况来决定是否可以继续进行,有以下两种可能。
- 假如协调者从所有的参与者获得的反馈都是 Yes 响应,那么就会执行事务的预执行。
- 假如有任何一个参与者向协调者发送了 No 响应,或者等待超时之后,协调者都没有接到参与者的响应,那么就执行事务的中断。
- 事务预执行:协调者向参与者发送
PreCommit
请求,并进入Prepared
阶段。参与者收到后会执行事务操作,并写本地的 redo 和 undo 日志。然后参与者会等待协调者最终的消息:DoCommit
或abort
,如果一定时间内没有收到协调者的消息,参与者将执行事务中断。- 事务中断:协调者向所有参与者发送
abort
请求。参与者收到后会中断事务。
DoCommit 阶段
该阶段进行真正的事务提交, 主要包含:
- 协调者向所有参与者发送
DoCommit
请求。 - 参与者提交事务。并在完成事务提交之后释放所有事务资源。
- 参与者 事务提交完之后,向协调者发送 Ack 响应。
- 协调者收到所有参与者的 Ack 后确认事务完成。