003 JTA的使用与理解
一:认识JTA
1.介绍
事物的ACID。
事务是计算机应用中不可或缺的组件模型,它保证了用户操作的原子性 ( Atomicity )、一致性 ( Consistency )、隔离性 ( Isolation ) 和持久性 ( Durabilily )。
操作必须保正 ACID 的事务属性:即要么全部成功,要么全部失败
2.本地事物
紧密依赖于底层资源管理器(例如数据库连接 ),事务处理局限在当前事务资源内。
此种事务处理方式不存在对应用服务器的依赖,因而部署灵活却无法支持多数据源的分布式事务。
3.数据库连接中使用本地事务
- public void transferAccount() {
- Connection conn = null;
- Statement stmt = null;
- try{
- conn = getDataSource().getConnection();
- // 将自动提交设置为 false,
- //若设置为 true 则数据库将会把每一次数据更新认定为一个事务并自动提交
- conn.setAutoCommit(false);
- stmt = conn.createStatement();
- // 将 A 账户中的金额减少 500
- stmt.execute("\
- update t_account set amount = amount - 500 where account_id = 'A'");
- // 将 B 账户中的金额增加 500
- stmt.execute("\
- update t_account set amount = amount + 500 where account_id = 'B'");
- // 提交事务
- conn.commit();
- // 事务提交:转账的两步操作同时成功
- } catch(SQLException sqle){
- try{
- // 发生异常,回滚在本事务中的操做
- conn.rollback();
- // 事务回滚:转账的两步操作完全撤销
- stmt.close();
- conn.close();
- }catch(Exception ignore){
- }
- sqle.printStackTrace();
- }
- }
4.分布式事物处理
分布式事务(Distributed Transaction)包括事务管理器(Transaction Manager)和一个或多个支持 XA 协议的资源管理器 ( Resource Manager )。
我们可以将资源管理器看做任意类型的持久化数据存储;
事务管理器承担着所有事务参与单元的协调与控制。
JTA 事务有效的屏蔽了底层事务资源,使应用可以以透明的方式参入到事务处理中;
但是与本地事务相比,XA 协议的系统开销大,在系统开发过程中应慎重考虑是否确实需要分布式事务。
若确实需要分布式事务以协调多个事务资源,则应实现和配置所支持 XA 协议的事务资源,如 JMS、JDBC 数据库连接池等。
5.使用 JTA 处理事务
- public void transferAccount() {
- Connection conn = null;
- Statement stmt = null;
- try{
- conn = getDataSource().getConnection();
- // 将自动提交设置为 false,
- //若设置为 true 则数据库将会把每一次数据更新认定为一个事务并自动提交
- conn.setAutoCommit(false);
- stmt = conn.createStatement();
- // 将 A 账户中的金额减少 500
- stmt.execute("\
- update t_account set amount = amount - 500 where account_id = 'A'");
- // 将 B 账户中的金额增加 500
- stmt.execute("\
- update t_account set amount = amount + 500 where account_id = 'B'");
- // 提交事务
- conn.commit();
- // 事务提交:转账的两步操作同时成功
- } catch(SQLException sqle){
- try{
- // 发生异常,回滚在本事务中的操做
- conn.rollback();
- // 事务回滚:转账的两步操作完全撤销
- stmt.close();
- conn.close();
- }catch(Exception ignore){
- }
- sqle.printStackTrace();
- }
- }
二:原理
1.原理介绍
将 JTA 的事务管理器和资源管理器理解为两个方面:面向开发人员的使用接口(事务管理器)和面向服务提供商的实现接口(资源管理器)。
其中开发接口的主要部分即为上述示例中引用的 UserTransaction 对象,开发人员通过此接口在信息系统中实现分布式事务;
而实现接口则用来规范提供商(如数据库连接提供商)所提供的事务服务,它约定了事务的资源管理功能,使得 JTA 可以在异构事务资源之间执行协同沟通。
2.体系架构
3.面向开发人员的接口为 UserTransaction
开发人员通常只使用此接口实现 JTA 事务管理,其定义了如下的方法:
- begin()- 开始一个分布式事务,(在后台 TransactionManager 会创建一个 Transaction 事务对象并把此对象通过 ThreadLocale 关联到当前线程上 )
- commit()- 提交事务(在后台 TransactionManager 会从当前线程下取出事务对象并把此对象所代表的事务提交)
- rollback()- 回滚事务(在后台 TransactionManager 会从当前线程下取出事务对象并把此对象所代表的事务回滚)
- getStatus()- 返回关联到当前线程的分布式事务的状态 (Status 对象里边定义了所有的事务状态,感兴趣的读者可以参考 API 文档 )
- setRollbackOnly()- 标识关联到当前线程的分布式事务将被回滚
4.面向提供商的实现接口主要涉及到 Transaction 两个对象
Transaction 代表了一个物理意义上的事务,在开发人员调用 UserTransaction.begin() 方法时 TransactionManager 会创建一个 Transaction 事务对象(标志着事务的开始)并把此对象通过 ThreadLocale 关联到当前线程。UserTransaction 接口中的 commit()、rollback(),getStatus() 等方法都将最终委托给 Transaction 类的对应方法执行。Transaction 接口定义了如下的方法:
- commit()- 协调不同的事务资源共同完成事务的提交
- rollback()- 协调不同的事务资源共同完成事务的回滚
- setRollbackOnly()- 标识关联到当前线程的分布式事务将被回滚
- getStatus()- 返回关联到当前线程的分布式事务的状态
- enListResource(XAResource xaRes, int flag)- 将事务资源加入到当前的事务中(在上述示例中,在对数据库 A 操作时 其所代表的事务资源将被关联到当前事务中,同样,在对数据库 B 操作时其所代表的事务资源也将被关联到当前事务中)
- delistResourc(XAResource xaRes, int flag)- 将事务资源从当前事务中删除
- registerSynchronization(Synchronization sync)- 回调接口,Hibernate 等 ORM 工具都有自己的事务控制机制来保证事务, 但同时它们还需要一种回调机制以便在事务完成时得到通知从而触发一些处理工作,如清除缓存等。这就涉及到了 Transaction 的回调接口 registerSynchronization。工具可以通过此接口将回调程序注入到事务中,当事务成功提交后,回调程序将被激活。
5.面向提供商的实现接口主要涉及到 TransactionManager
本身并不承担实际的事务处理功能,它更多的是充当用户接口和实现接口之间的桥梁。
下面列出了 TransactionManager 中定义的方法,可以看到此接口中的大部分事务方法与 UserTransaction 和 Transaction 相同。
在开发人员调用 UserTransaction.begin() 方法时 TransactionManager 会创建一个 Transaction 事务对象(标志着事务的开始)并把此对象通过 ThreadLocale 关联到当前线程上;
同样 UserTransaction.commit() 会调用 TransactionManager.commit(), 方法将从当前线程下取出事务对象 Transaction 并把此对象所代表的事务提交, 即调用 Transaction.commit()。
- begin()- 开始事务
- commit()- 提交事务
- rollback()- 回滚事务
- getStatus()- 返回当前事务状态
- setRollbackOnly()
- getTransaction()- 返回关联到当前线程的事务
- setTransactionTimeout(int seconds)- 设置事务超时时间
- resume(Transaction tobj)- 继续当前线程关联的事务
- suspend()- 挂起当前线程关联的事务
在系统开发过程中会遇到需要将事务资源暂时排除的操作,此时就需要调用 suspend() 方法将当前的事务挂起:在此方法后面所做的任何操作将不会被包括在事务中,在非事务性操作完成后调用 resume()以继续事务
6.JTA 实现类图
UserTransactionImpl 实现了 UserTransaction 接口,
TransactionManagerImpl 实现了 TransactionManager 接口,
TransactionImpl 实现了 Transaction 接口
7.分布式事物数据源
为什么必须从支持事务的数据源中获得的数据库连接才支持分布式事务呢?
其实支持事务的数据源与普通的数据源是不同的,它实现了额外的 XADataSource 接口。
我们可以简单的将 XADataSource 理解为普通的数据源(继承了 java.sql.PooledConnection),只是它为支持分布式事务而增加了 getXAResource 方法。
另外,由 XADataSource 返回的数据库连接与普通连接也是不同的,此连接除了实现 java.sql.Connection 定义的所有功能之外还实现了 XAConnection 接口。
我们可以把 XAConnection 理解为普通的数据库连接,它支持所有 JDBC 规范的数据库操作,不同之处在于 XAConnection 增加了对分布式事务的支持。
8.事物资源类图
应用程序从支持分布式事务的数据源获得的数据库连接是 XAConnection 接口的实现,而由此数据库连接创建的会话(Statement)也为了支持分布式事务而增加了功能。
XAResource 与 Xid: XAResource 是 Distributed Transaction Processing: The XA Specification 标准的 Java 实现,它是对底层事务资源的抽象,定义了分布式事务处理过程中事务管理器和资源管理器之间的协议,各事务资源提供商(如 JDBC 驱动,JMS)将提供此接口的实现。使用此接口,开发人员可以通过自己的编程实现分布式事务处理,但这些通常都是由应用服务器实现的(服务器自带实现更加高效,稳定) 为了说明,我们将举例说明他的使用方式。
在使用分布式事务之前,为了区分事务使之不发生混淆,必须实现一个 Xid 类用来标识事务,可以把 Xid
想象成事务的一个标志符,每次在新事务创建是都会为事务分配一个 Xid,Xid 包含三个元素:formatID、gtrid(全局事务标识符)和
bqual(分支修饰词标识符)。
formatID 通常是零,这意味着你将使用 OSI CCR(Open Systems Interconnection Commitment,
Concurrency 和 Recovery 标准)来命名;如果你要使用另外一种格式,那么 formatID 应该大于零,-1 值意味着
Xid 为无效。
gtrid 和 bqual 分别包含 64 个字节二进制码来分别标识全局事务和分支事务, 唯一的要求是 gtrid 和 bqual 必须是全局唯一的。
003 JTA的使用与理解的更多相关文章
- 【转】关于JTA,XA,ACID
对于我们这种初学者,可能会使用spring带给我们的@Transactional,可能了解JTA,可能会使用jotm.atomikos,又会遇到一些名词XA,支持XA的数据库驱动等等诸多问题,然后就会 ...
- Linux默认权限的计算公式(个人理解性的笔记~)
先记下Linux下的权限可以分为 常见的 r(Read,读取):对文件,读取文件内容的权限:目录来说,具有浏览目 录的权限.权限值=4 w(Write,写入):对文件而言,具有新增.修改文件内容的权限 ...
- 分布式事务操作之Spring+JTA
什么是分布式事务?在网上找了一段比较容易理解的"定义". 分布式事务是指事务的参与者.支持事务的服务器.资源管理器以及事务管理器分别位于分布系统的不同节点之上,在两个或多个网络计算 ...
- JTA 深度历险 - 原理与实现
转自http://www.ibm.com/developerworks/cn/java/j-lo-jta/ 在 J2EE 应用中,事务是一个不可或缺的组件模型,它保证了用户操作的 ACID(即原子.一 ...
- hibernate知识点理解
1.只有业务逻辑层出现的问题? 1.切换数据库麻烦 2.sql编写起来麻烦 3.我们的程序员不需要关注数据库,只希望关心业务本身 2.hibernate的好处 1.程序员只关心业务逻辑,使角色更加清楚 ...
- [反汇编练习] 160个CrackMe之003
[反汇编练习] 160个CrackMe之003. 本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注 ...
- Spring JTA multiple resource transactions in Tomcat with Atomikos example--转载
原文地址:http://www.javacodegeeks.com/2013/07/spring-jta-multiple-resource-transactions-in-tomcat-with-a ...
- 深刻理解C#的传值调用和传引用调用
传值调用和传引用调用是几乎所有主流语言都会涉及到的问题,下面我谈谈我对C#中传值调用和传引用调用的理解. 1. 一般对C#中传值调用和传引用调用的理解 如果传递的参数是基元类型(int,float等) ...
- JTA 深度历险 - 原理与实现---转
利用 JTA 处理事务 什么是事务处理 事务是计算机应用中不可或缺的组件模型,它保证了用户操作的原子性 ( Atomicity ).一致性 ( Consistency ).隔离性 ( Isolatio ...
随机推荐
- css3-自定义字体
参考链接http://www.w3cplus.com/content/css3-font-face 出处W3CPLUS css3-自定义字体 @font-face @font-face是CSS3中 ...
- Java并发编程原理与实战二十:线程安全性问题简单总结
一.出现线程安全性问题的条件 •在多线程的环境下 •必须有共享资源 •对共享资源进行非原子性操作 二.解决线程安全性问题的途径 •synchronized (偏向锁,轻量级锁,重量级锁) •vol ...
- Kafka安装验证及其注意
一.Zookeeper 配置文件说明: # the directory where the snapshot is stored. dataDir=/tmp/zookeeper # the port ...
- IOC轻量级框架之Unity
任何事物的出现,总有它独特的原因,Unity也是如此,在Unity产生之前,我们是这么做的 我们需要在一个类A中引用另一个类B的时候,总是将类B的实例放置到类A的构造函数中,以便在初始化类A的时候,得 ...
- 男女通用的减肥计划 10分钟家庭hiit训练
在大城市的年轻人,一般都会比较忙,晚上下班吃完饭,到家就要8-9点了,再让他们去,有时候真的不太方便. 其实你如果想要,也不一定要,在家里做hiit运动,就可以了. hiit(高强度间歇运动),是目前 ...
- 简单几招,解决jQuery.getJSON的缓存问题
今天做测试工作,发现了一个令我费解的问题,jquery的getJson方法在firefox上运行可以得到返回的结果,但是在ie8上测试,竟发现没有发送请求,故不能取到任何返回的结果,经历了一翻周折,找 ...
- 修改elasticsearch5,搜索结果最大10000
一:在Linux服务器中执行如下命令(开启es服务) curl -XPUT http://服务器ip:9200/索引名称/_settings -d '{ "index" : { & ...
- 微服务深入浅出(11)-- SpringBoot整合Docker
添加Dockerfile 在目录src/main/resources目录下店家Dockerfile文件: From java MAINTAINER "Eric"<eric.l ...
- Python练习-递归二分算法
# 编辑者:闫龙 #递归,二分算法演示 l = [i for i in range(1,100)]#定义一个列表l,并追加1-99的所有数字 def FindNum(num,l):#定义函数FindN ...
- JavaScript 优雅的实现方式包含你可能不知道的知识点
有些东西很好用,但是你未必知道:有些东西你可能用过,但是你未必知道原理. 实现一个目的有多种途径,俗话说,条条大路通罗马.很多内容来自平时的一些收集以及过往博客文章底下的精彩评论,收集整理拓展一波,发 ...