A. 分布式事务概述
1、事务简介
事务(Transaction)是访问并可能更新数据库中各种数据项的一个程序执行单元(unit)。在关系数据库中,一个事务由一组SQL语句组成。事务应该具有4个属性:原子性、一致性、隔离性、持久性。这四个属性通常称为ACID特性。
原子性(atomicity):个事务是一个不可分割的工作单位,事务中包括的诸操作要么都做,要么都不做。
一致性(consistency):事务必须是使数据库从一个一致性状态变到另一个一致性状态,事务的中间状态不能被观察到的。
隔离性(isolation):一个事务的执行不能被其他事务干扰。即一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行的各个事务之间不能互相干扰。隔离性又分为四个级别:读未提交(read uncommitted)、读已提交(read committed,解决脏 读)、可重复读(repeatable read,解决虚读)、串行化(serializable,解决幻读)。
持久性(durability):持久性也称永久性(permanence),指一个事务一旦提交,它对数据库中数据的改变就应该是永久性的。接下来的其他操作或故障不应该对其有任何影响。
任何事务机制在实现时,都应该考虑事务的ACID特性,包括:本地事务、分布式事务,及时不能都很好的满足,也要考虑支持到什么程度。
2、 本地事务
大多数场景下,我们的应用都只需要操作单一的数据库,这种情况下的事务称之为本地事务(Local Transaction
)。本地事务的ACID特性是数据库直接提供支持。本地事务应用架构如下所示:
在JDBC编程中,我们通过java.sql.Connection
对象来开启、关闭或者提交事务。代码如下所示:
1 Connection conn = ... //获取数据库连接 2 conn.setAutoCommit(false); //开启事务 3 try{ 4 //...执行增删改查sql 5 conn.commit(); //提交事务 6 }catch (Exception e) { 7 conn.rollback();//事务回滚 8 }finally{ 9 conn.close();//关闭链接 10 }
此外,很多java应用都整合了spring,并使用其声明式事务管理功能来完成事务功能。一般使用的步骤如下:
1、配置事务管理器。spring提供了一个PlatformTransactionManager
接口,其有2个重要的实现类:
DataSourceTransactionManager
:用于支持本地事务,事实上,其内部也是通过操作java.sql.Connection来开启、提交和回滚事务。
JtaTransactionManager
:用于支持分布式事务,其实现了JTA规范,使用XA协议进行两阶段提交。需要注意的是,这只是一个代理,我们需要为其提供一个JTA provider,一般是Java EE容器提供的事务协调器(Java EE server's transaction coordinator),也可以不依赖容器,配置一个本地的JTA provider。
2、 在需要开启的事务的bean的方法上添加@Transitional
注解
可以看到,spring除了支持本地事务,也支持分布式事务,下面我们先对分布式事务的典型应用场景进行介绍。