目录
一、事务简介
事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元。在关系型数据库中,一个事务由一组sql语句组成。事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常被称为ACID特性。
**原子性(atomicity):**一个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
**一致性(consistency):**事务必须是使数据库从一个一致性状态变到另一个一致性状态,事务的中间状态不能被观察到的。
**隔离性(isolation):**一个事务的执行不能被其它事务所干扰。即一个事务内部的操作及使用的数据对并发的其它事务是隔离的,并发执行的各个事务之间不能互相干扰。隔离性又分为四个级别:读未提交(read uncommitted)、读已提交(read committed,解决脏读)、可重复读(repeatable read,解决虚读)、串行化(serializable,解决幻读)。
**持久性(durability):**持久性也称为永久性,指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其它操作或故障不应该对其有任何影响。
任何事务机制在实现时,都应该考虑事务的ACID特性,包括:本地事务,分布式事务,即使不能都很好的满足,也要考虑支持到什么程度。
二、本地事务
@Transaction
大多数场景下,我们的应用都只需要操作单一的数据库,这种情况下的事务被称之为本地事务(Local Transaction)。本地事务的ACID特性是数据库直接提供支持。本地事务应用架构如下所示:
在JDBC编程中,我们通过java.sql.Connection对象来开启、关闭或者提交事务。代码如下所示:
Connection conn = ......; //获取数据库连接
conn.setAutoCommit(false); //开启事务
try{
//执行增删改查sql
conn.commit(); //提交事务
}catch(Exception e){
conn.rollback(); //事务回滚
}finally{
conn.close(); //关闭连接
}
三、常见的分布式事务解决方案
1、seata阿里分布式事务框架
2、消息队列
3、saga
4、XA
他们都有一个共同点,都是"两阶段(2PC)"。两阶段是指完成整个分布式事务,划分成两个步骤完成。
实际上这四种常见的分布式事务解决方案,分别对应着分布式事务的四种模式:AT、TCC、Saga、XA;
四种分布式事务模式,都有各自的理论基础,分别在不同的时间被提出;每种模式都有他的适用场景,同样每个模式也都诞生有各自的代表产品,而这些代表产品,可能就是我们常见的(全局事务、基于可靠消息、最大努力通知、TCC)。
在看具体实现之前,先说下分布式事务的理论基础。
分布式事务理论基础
解决分布式事务,也有相应的规范和协议。分布式事务相关的协议有2PC、3PC。
由于三阶段提交协议3PC非常难实现,目前市面主流的分布式事务解决方案都是2PC协议。
有些文章分析2PC时,几乎都会用TCC两阶段的例子,第一阶段try,第二阶段完成confirm或cancel。其实2PC并不是专为实现TCC设计的,2PC具有普适性,目前绝大多数分布式事务解决方案都是以两阶段提交协议2PC为基础的。
TCC(Try-Confirm-Cancel)实际上是服务化的两阶段提交协议。
两阶段提交协议
顾名思义,分为两个阶段:Prepare和Commit。
Prepare:提交事务请求
基本流程如下图:
- 询问:协调者向所有参与者发送事务请求,询问是否可执行事务操作,然后等待各个参与者的响应。
- 执行:各个参与者接收到协调者事务请求后,执行事务操作(例如更新一个关系型数据库表中的记录)并将Undo和Redo信息记录事务日志中。
- 响应:如果参与者成功执行了事务并写入Undo和Redo信息,则向协调者返回YES响应,否则返回NO响应。当然,参与者也可能宕机,从而不会返回响应。
Commit:执行事务提交
执行事务提交分别两种情况,正常提交和回滚。
正常提交事务
流程如下图 :
- commit请求:协调者向所有参与者发送Commit请求。
- 事务提交:参与者收到Commit请求后,执行事务提交,提交完成后释放事务执行期占用的所有资源。
- 反馈结果:参与者执行事务提交后向协调者发送Ack响应。
- 完成事务:接收到所有参与者的Ack响应后,完成事务提交。
回滚事务
在执行Prepare步骤过程中,如果某些参与者执行事务失败、宕机或协调者之间的网络中断,那么协调者就无法收到参与者的YES响应,或者某个参与者返回了NO响应,此时,协调者就会进入回滚流程,对事务进行回滚。
流程如下图:
- rollback请求:协调者向所有参与者发送Rallback请求。
- 事务回滚:参与者收到Rallback请求后,使用Prepare阶段的Undo日志执行事务回滚,完成后释放事务执行期占用的所有资源。
- 反馈结果:参与者执行事务回滚后向协调者发送Ack响应。
- 回滚事务:接收到所有参与者的Ack响应后,