事务的目的就是为了确保数据的完整性,一个事务通常被定义为一个包含多步操作的不可分割的单元。事务具有下列四个特征:
原子性(Atomicity):事务能够以两种方式结束:提交或回滚。当事务被提交后,在这个事务边界内对数据的更改会被保存。当事务回滚,所有对数据的更改都要被恢复。
一致性(Consistency):如果事务失败,数据的完整性将被保护。
隔离性(Isolation):并发执行的事务都应该表现为独立执行。
持久性(Durability):事务提交后的改变应该是持久的。
在J2EE平台中,可管理的事务资源包括三种,数据库连接池、消息系统连接和符合J2EE™连接器架构(J2EE Connector Architecture,JCA)的资源。Apusic应用服务器中的事务管理器提供对以上三种资源的事务管理。
J2EE通过两个规范支持分布式事务:
Java Transaction API (JTA)
Java Transaction Service (JTS)
JTA是上层的、中立于协议的应用程序接口,允许应用和应用服务器访问事务。JTS规定事务管理的实现必须支持JTA,并且实现OMG对象事务服务(Object Transaction Service,OTS)规范的Java映射。JTS使用IIOP协议传播事务。 Apusic应用服务器的事务管理器完全支持JTS和JTA,EJB容器使用JTA和JTS进行交互。
EnableLog:
打开事务日志。只有打开事务日志,才会启用分布式事务恢复功能。默认为False(关闭事务日志)。
RetryTimeout
发生通讯故障时重试的时间,默认600秒,超出该时间将不再重试,而是通知用户因通讯故障而导致出错。0 表示会永远重试。
RetryInterval
发生通讯故障时重试的时间间隔。默认60秒。
HeuristicDecision
作为事务从属Coordinator的应用服务器如果在RetryTimeout指定的时间内无法从其上级Coordinator处获得事务完成方向的指示,会自行决定应该提交还是回滚。取值必须为“commit”或“rollback”两者之一,默认为“rollback”。若不想做出启发式决定,而是一直等待直到条件成熟时再从上级Coordinator得到指示,请记得把RetryTimeout设为0,此时会一直尝试,并且应用服务器启动过程暂停,不对外提供服务,直到所有事务恢复完成为止。
TxServerID
事务管理器的ID,用于标识事务管理器的一个字符串,默认无需设置。每个应用服务器的实例包含一个事务管理器,在事务管理器把XAs资源纳入到事务中进行管理时,会给资源赋予一个事务分支ID,TxServerID的信息会被加入到这个事务分支ID中。在一个事务包含超过一个事务管理器时(即跨应用服务器的事务),如果不同应用服务器配置了相同参数的数据源,在事务恢复时,必须区分哪个XA资源是归属哪个事务管理器所管理,此时必须为不同的事务管理器配置不同的TxServerID,否则,会出现事务管理器与XA资源的失配,导致事务恢复过程出错。
Apuisc应用服务器的分布式事务恢复功能默认关闭,若要开启该功能,需要配置apusic.conf中的TransactionService服务EnableLog参数为True。 其他参数酌情配置,请参考第 35.1 节 “配置事务服务”。
在应用服务器重启时,如果存在需要恢复的事务,会自动进行事务的恢复,有关事务恢复的信息会在Apusic的日志中体现,会告知共有多少个事务需要恢复,以及经过恢复后,有多少个事务已提交,有多少个事务已回滚,有多少个事务尚在存疑状态,有多少个事务恢复失败(等待条件成熟时下次重启应用服务器再次执行恢复)。
应用服务器关闭后,不论是正常关闭还是异常终止,如果有需要恢复的事务,logs/tx目录会留下事务日志文件,事务日志文件格式为二进制,只用于重启时的事务恢复,如果该目录为空,表示没有需要恢复的事务。
在重启恢复事务的过程中如果有事务恢复失败,可等条件成熟时再次重启进行恢复。若重启恢复事务过程中应用服务器再次崩溃,可再次重启应用服务器继续完成恢复过程。若应用服务器所在的机器无法工作,可以把logs/tx目录中的事务日志文件拷贝到其他机器上的相同配置的Apusic应用服务器的同名目录中,启动该应用服务器完成事务的恢复。
Apusic应用服务器的事务服务支持在EJB和客户端中使用事务。
Apusic应用服务器的EJB容器支持两种类型的事务管理:
Bean管理事务(程序型的事务划分)
容器管理事务(声明型的事务划分)
客户端通过JNDI查找(lookup)java:comp/UserTransaction获得服务器的事务服务,返回的对象实现了javax.transaction.UserTransaction接口。客户端通过调用UserTransaction的begin、commit和rollback方法管理事务。使用JNDI查找UserTransaction接口的范例代码如下:
InitialContext ic = new InitialContext(); String txName = "java:comp/UserTransaction"; UserTransaction tx = (javax.transaction.UserTransaction)ic.lookup(txName); tx.begin(); // transacted commands, such as JDBC calls tx.commit();