## 为什么二阶段、三阶段保证不了强一致,seata 可以?
二阶段提交和三阶段提交是作为一种指导思想,而 Seata 框架则是具体在思想上的实现方案,通过增加一些约束和措施来保证数据的一致性。
Seata 架构提供了四种不同的分布式事务解决方案
- XA 模式:强一致性分阶段事务模式,牺牲了一定的可用性,无业务侵入
- TCC 模式:最终一致的分阶段事务模式,有业务侵入
- AT 模式:最终一致的分阶段事务模式,无业务侵入,也是 Seata 的默认模式
- SAGA 模式:最终一致,长事务模式,有业务侵入
其中只有 XA 模式做到了强一致性,其他都是弱一致性,但是数据还是要最终一致的,才会保证业务不出错。
这里以 XA 为例子我们来分析一下:
> 首先,XA 是规范,目前主流数据库都实现了这种规范,实现的原理都是**基于两阶段提交**。
一阶段:
- 1.事务协调者通知每个事物参与者执行本地事务
- 2.本地事务执行完成后报告事务执行状态给事务协调者,此时事务不提交,继续持有数据库锁
二阶段:事务协调者基于一阶段的报告来判断下一步操作
- 如果一阶段都成功,则通知所有事务参与者,提交事务
- **如果一阶段任意一个参与者失败,则通知所有事务参与者回滚事务**
> XA分两阶段提交,第一阶段进行事务注册,将事务注册到TC,然后执行[sql语句](https://so.csdn.net/so/search?q=sql语句&spm=1001.2101.3001.7020),第二阶段TC判定有无事务执行出错,如果没错则通知所有事务提交,否则回滚,在第一到第二阶段过程中事务一直占有数据库锁,因此性能低,但所有事务要么一起提交,要么一起回滚,所以能实现强一致性。
Seata 对原始的 XA 模式做了简单的封装和改造,以适应自己的事务模型:
我们可以看出:Seata XA基于二阶段协议进行实现,为了保证一致性做了一些约束。
- `数据锁定`:数据在整个事务处理过程结束前,都被锁定,读写都按隔离级别的定义约束起来。(数据锁定是为了获得更高隔离性和全局一致性,所要付出的代价。这也是 XA 的缺点,因为一阶段需要锁定数据库资源,等待二阶段结束才释放,**性能较差。**且依赖关系型数据库实现事务。)
- `协议阻塞`:XA prepare 后,分支事务进入阻塞阶段,收到 XA commit 或 XA rollback 前必须阻塞等待。
本质上,Seata 已经支持的 3 大事务模式:AT、TCC、Saga 都是 补偿型 的。只有 XA 能全局一致性,其实说白了就行依赖数据库对资源控制,从而实现对数据的访问有效隔离,满足全局数据一致性。