Offer来了:Java面试核心知识点精讲(框架篇)
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.8 事务

事务是Web应用中不可缺少的组件模型,它保证了用户操作的原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durabilily)。事务分本地事务和分布式事务两种。

1.8.1 本地事务

本地事务基于数据库资源实现,事务串行地在JDBC连接上执行,本地事务将事务处理局限在当前事务资源内。其特点是使用灵活但无法支持多数据源事务操作。在数据库连接中使用本地事务的代码示例如下。

在上述代码中,首先通过conn.setAutoCommit(false)设置数据库连接为非自动提交,然后分别提交了两条更新语句,最后通过conn.commit()提交事务。如果数据库操作成功,则事务完成;如果操作失败,则通过conn.rollback()回滚事务。

1.8.2 分布式事务

分布式事务(Distributed Transaction)提供了跨数据库的分布式事务操作的数据一致性,跨数据库的一致性包含同一类型数据库的多个数据库实例服务的一致性(例如多个MySQL的事务一致性)和多个不同类型数据库的数据一致性(例如MySQL和Oracle之间的事务一致性)两种情况。

Java事务编程接口(Java Transaction API,JTA)和Java事务服务(Java Transaction Service,JTS)为J2EE平台提供了分布式事务服务。分布式事务包括一个事务管理器(Transaction Manager)和一个或多个支持XA协议(XA协议是由X/Open组织提出的分布式事务的规范,XA规范主要定义了事务管理器和资源管理器之间的接口)的资源管理器(Resource Manager)。其中,事务管理器负责所有事务参与单元的协调与控制,资源管理器负责不同的数据库具体的事务执行操作。具体使用代码如下。

在上述代码中,首先定义了一个分布式事务管理器UserTransaction,然后定义了2个连接池connA和connB,接着通过userTx.begin()启动事务并向两个数据库连接提交2个更新请求,最后通过userTx.commit()统一提交事务。如果执行成功,则事务完成;如果失败,则通过userTx.rollback()回滚事务。

1.8.3 两阶段提交协议

两阶段提交协议用于保证分布式事务的原子性,即所有数据库节点要么全部都执行要么全部不执行,其执行过程主要分为两个阶段:第一阶段为准备阶段,第二阶段为提交阶段,数据库两阶段提交协议如图1-6所示。

图1-6 数据库两阶段提交协议

1.准备阶段

事务管理器(事务协调者)为每个资源管理器(事务参与者)都发送Prepare消息,每个参与者要么都直接返回失败(例如权限验证失败),要么都在本地执行事务,写本地的redo和undo日志但是不提交,以达到“万事俱备,只欠东风”的状态。

2.提交阶段

如果事务协调者收到了某个事务参与者的事务操作失败回复或等待事务参与者反馈超时,则事务协调者为每个事务参与者发送回滚(Rollback)消息,事务参与者再执行回滚本地事务操作;如果事务协调者在规定时间内收到了所有事务参与者的成功回复,则发送提交(Commit)消息,事务参与者在本地执行事务提交操作并执行事务。

两阶段提交的目的是尽可能晚地提交事务,在提交事务前尽可能确保每个数据库都正常运行,并确保该事务对应的SQL语句能够在每个数据库上都正常执行,同时将数据的写日志操作提前完成,防止事务执行过程中发生意外。事务的执行和释放是在JPA中基于锁来实现控制的。