请教WEBLOGIC 8中DB2python中数据库连接池池报XAER

&&&&&&&&&&&&&&&&&&
posts - 42,comments - 83,trackbacks - 0
留言簿(16)
阅读排行榜
评论排行榜
&&&&&&&&某些时候,在weblogic执行XA操作的时候,我们会碰到如下的错误:
&&&&&&&&java.sql.SQLException: Unexpected exception while enlisting XAConnection java.sql.SQLException: XA error: XAER_NOTA : The XID is not valid start() failed on resource 'weblogic.jdbc.jta.DataSource': XAER_NOTA : The XID is not valid&
&&&&&&&& XAER_NOTA说明transaction branch在ResourceManager端(DB, MQ等)不存在。不存在通常由两种可能:transaction branch被timeout掉了,另外一种情况就是这个branch压根就没有在ResourceManager端发起过。
&&&&&&&&这篇文章主要针对2做一下说明,对于1,我们可以在Weblogic的XAConnectionPool设定中,&并对此设定一个合理的值,建议这个值比global transaction&timeout大。这样weblogic在调用xaStart()的时候,会通知RM,该branch的timeout时间,而不是使用RM自己默认的timeout(对于Oracle, 默认为60秒,但一般会在120秒的时候,tx branch才会被Oracle timeout掉)。
&&&&&&&&对于2, 一般会跟配置有关系,比如两个XA datasource指向同一个XAConnectionPool, 或多个XAConnectionPool指向同一个Database,我们以多个datasource指向同一connection为例:
&&&&&& 1:假如我们有如下的配置环境:
&&&&&&&& XADatasource_11----&XAPool_A----&Databse_A
&&&&&&&& XADatasource_21----&XAPool_B----&Databse_B
&&&&& &&这样的配置环境中,我们做XA相关的操作是没有问题的。
&1&&&&&&&&&public&void&xaTest()
&2&&&&&&&{
&3&&&&&&&&&&&&try{
&4&&&&&&&&&&&&&&&&UserTransaction&tx&=&getUserTransaction();
&5&&&&&&&&&&&&&&&&tx.setTransactionTimeout(<span style="color: #00);
&6&&&&&&&&&&&&&&&&tx.begin();
&7&&&&&&&&&&&&&&&&Connection&conn1&=&getConnection("t3://localhost:7011",&XADatasource_11);
&8&&&&&&&&&&&&&&&&Connection&conn2&=&getConnection("t3://localhost:7021",&XADatasource_21);
&9&&&&&&&&&&&&&&&&this.executeInsertInPSMT(conn1,&null);
<span style="color: #&&&&&&&&&&&&&&&&this.executeAnoInsertInPSMT(conn2,&null);
<span style="color: #&&&&&&&&&&&&&&&&conn1.close();
<span style="color: #&&&&&&&&&&&&&&&&conn2.close();
<span style="color: #&&&&&&&&&&&&&&&&tx.commit();
<span style="color: #&&&&&&&&&&&&}catch(Exception&e){}
<span style="color: #&&&&&&&}
&&&&& 2:如果基于业务需要,我们需要额外配置两个XA Datasource,分别指向 XAPool_A、XAPool_B,如下:
&&&&&&& XADatasource_12----〉XAPool_A
&&&&&&& XADatasource_22----〉XAPool_B
&&&&& 部署Datasource的时候,Weblogic会判断这个Datasource是不是XA类型 的,如果是XA类型的Datasource,我们需要将这个datasource实例注册到Process- wide的resourceDescriptorList中,如下:
&&&&& registerResource(poolName, (XAResource)driverInstance, registrationProperties);
&&&&& 在register前,我们先调用unregisterResource(poolName)将该poolName 对应的resource从 resourceDescriptorList中unregister掉。这样 XADatasource_12、XADatasource_22部署后,我们可以看到process-wide的 resourceDescriptorList中的对象变化:
&&&&&&& 部署前:XADatasource_11, XADatasource_21
&&&&&&& 部署后:XADatasource_12, XADatasource_22
&&&&&&& 注意:如果XADatasource11、12, XADatasource_21、22不存在多数据源 指向同连接池的话,部署后,四个Datasource应该都出现在 resourceDescriptorList中。
&&&&& 3:如果我们此时执行xaTest()测试代码,过程如下:
&&&&&&&&& 3.1:Connection conn1 = getConnection("t3://localhost:7011", XADatasource_11);
&&&&&&&&&&&&&& 在getConnection()的时候, weblogic中需要将 XAResource enlist到当前的transaction中,如下:
&&&&&&&&&&&&&& Thread [ExecuteThread: '14' for queue: 'weblogic.kernel.Default'] (Suspended)&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&& ServerTransactionImpl.enlistResource(XAResource) line: 412&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&& DataSource.enlist(Transaction) line: 1519&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&& DataSource.refreshXAConnAndEnlist(XAConnection, JTAConnection, boolean) line: 1459&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&& DataSource.getConnection() line: 452&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&& DataSource.connect(String, Properties) line: 410&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&& RmiDataSource.getConnection() line: 329&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&& RmiDataSource_WLSkel.invoke(int, InboundRequest, OutboundResponse, Object) line: not available&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&& ClusterableServerRef(BasicServerRef).invoke(RuntimeMethodDescriptor, InboundRequest, OutboundResponse) line: 492&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&& ClusterableServerRef(ReplicaAwareServerRef).invoke(RuntimeMethodDescriptor, InboundRequest, OutboundResponse) line: 108&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&& BasicServerRef$1.run() line: 435&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&& AuthenticatedSubject.doAs(AbstractSubject, PrivilegedExceptionAction) line: 363&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&& SecurityManager.runAs(AuthenticatedSubject, AuthenticatedSubject, PrivilegedExceptionAction) line: 147&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&& ClusterableServerRef(BasicServerRef).handleRequest(InboundRequest) line: 430&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&& BasicExecuteRequest.execute(ExecuteThread) line: 35&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&& ExecuteThread.execute(ExecuteRequest) line: 224&&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&& ExecuteThread.run() line: 183&
&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&& 3.1.1: 在enlistResource()中,我们首先检查 XADatasource_11实例对应的resourceDescriptor在process- wide的 resourceDesriptorList中是否存在(很显然,它是不存在的,因为我们在部署 XADatasource_12的时候,它被 unregister掉了)。接下来,我们会检查 XADatasource_11实例对应的resourceInfo在transaction-wide 的 resourceInfoList中是否存在(因为这个transaction刚刚开始, resourceInfoList中没有任何 resource)。因为XADatasource_11实例对应的 resourceInfo在resourceInfoList中不存在,我们需要创建一个 XAServerResourceInfo来和XADatasource_11实例关联。如下:
&&&&&&&&&&&&&& ri = new XAServerResourceInfo(xar)
&&&&&&&&&&&&&&
&&&&&&&&&&&&&& 3.1.2: 在XAServerResourceInfo初始化中,我们会再次检 查和XADatasource_11实例对应的resourceDescriptor 是否在 resourceDescriptorList中存在(同样,它依然是不存的)。因为 resourceDescriptor在 resourceDescriptorList中不存在,我们会从xaResource 获取xarName , 如下:
&&&&&&&&&&&&&& String xarName = aXar.getClass().getName(); //weblogic.jdbc.jta.DataSource
&&&&&&&&&&&&&& 然后根据xarName 去resourceDescriptorList中继续检 查,是否存在该xarName 对应的resourceDesriptor。因为此时 resourceDescriptorList中对象如下:
&&&&&&&&&&&&&& By instance: XADatasource_12, XADatasource_22
&&&&&&&&&&&&&& By name: XAPool_A, XAPool_B
&&&&&&&&&&&&&&
&&&&&&&&&&&&&& 3.1.3: 所以无论是根据XADatasource_11实例,还是根据 weblogic.jdbc.jta.DataSource都不能从resourceDescriptorList中找到与其对应 的 resourceDescriptor。这是我们会根据xarName (weblogic.jdbc.jta.DataSource)创建一个 resourceDescriptor,如下:
&&&&&&&&&&&&&&& rd = (XAResourceDescriptor) create(xarName, aXar, DYNAMIC);
&&&&&&&&&&&&&&
&&&&&&&&&&&&&& 3.1.4: XAResourceDescriptor创建完成后,我们会将该 resourceDescriptor放入 resourceDescriptorList中,此时 resourceDescritporList中对象如下:
&&&&&&&&&&&&&& By instance: XADatasource_12, XADatasource_22,XADatasource_11
&&&&&&&&&&&&&& By name: XAPool_A, XAPool_B,weblogic, jdbc.jta.DataSource
&&&&&&&&&&&&&& 这是返回到3.1.2的XAServerResourceInfo初始化 中,我们将该resourceInfo的xaResource设定为传入的参数 xar,resourceInfo的 name被设定为3.1.3中的xarName,即weblogic.jdba.jta.DataSource.
&&&&&&&&&&&&&& 3.1.5:回到3.1.1, XAServerResourceInfo实例创建后, 我们根据resourceInfo的name,来检查当前tx的resourceInfoList 是否存在对应 的resourceInfo,对于一个刚刚开始的transaction,此时它的resourceInfoList 是空的。如果同名的 resourceInfo被detect到,我们会将该resourceInfo的 enlistElseWhere置为true(即已被enlist)。因为我们新创建的resourceInfo之 前没有被enlist过,所以我们需要调用resourceInfo的enlist()来将 XADatasource_11 enlist到当前tx中。此时当前transaction的resourceInfoList 对象如下:
&&&&&&&&&&&&&& By instance: XADatasource_11
&&&&&&&&&&&&&& By name: weblogic.jdbc.jta.Datasource
&&&&&&&&&&&&&
&&&&&&&&&&&&&& 3.1.6: 在resourceInfo的enlist中,如果resourceInfo的 enlistElseWhere为true, 将要传递给xaStart的flag为TMNOFLAGS, 否则为 TMJOIN。然后获取调用
&&&&&&&&&&&&&& Xid bXid = getXIDwithBranch((XidImpl)tx.getXID())
&&&&&&&&&&&&&& 获取事务分支ID, 最后综合BRANCH_ID, FLAGS 来通知RESOURCE_MANAGER(DataBase_A)启动一个事务。
&&&&&&&&&&&&&& 注意:TMNOFLAGS是通知RESOURCE_MANAGER启动 一个新事务
&&&&&&&&&&&&&&&&&&&& TMJOIN是将当前线程和BRANCH_ID 对应的事务关联。
&&&&&&&&&& 3.2:Connection conn1 = getConnection("t3://localhost:7011", XADatasource_11);
&&&&&&&&&&&&&& 3.1中的动作会被重复,但中间的差别如下:
&&&&&&&&&&&& &&
&&&&&&&&&&&& & 3.2.1:XADatasource_21实例对应resourceDescriptor同样不会 在resourceDescriptorList中被发现,因为它已经在register XADatasource_22的 时候被unregister掉了。XADatasource_21对应的resourceInfo不存于当前 transaction的resourceInfoList中,resourceInfoList中只有XADatasource_11实 例对应的一个名叫weblogic.jdbc.jta.DataSource的对象,它在3.1.5中被置入。 同3.1.1,我们这时候需要根据 XADatasource_21, 创建一个与其对应的 resourceInfo, 如下:
&&&&&&&& ri = new XAServerResourceInfo(xar)
&&&&&&&&&&&&&
&&&&&&&&&&&&&& 3.2.2:创建XAServerResourceInfo的时候,因为此时 resourceDescriptorList中对象如下(参考 3.1.4):
&&&&&&&& By instance: XADatasource_12, XADatasource_22, XADatasource_11
&&&&&&&& By name: XAPool_A, XAPool_B,weblogic,jdbc.jta.DataSource
&&&&&&&& 根据XADatasource_21我们找不到这个resourceDescriptor,但 我们能根据xarName,即weblogic.jdbc.jta.Datasource找到一个 resourceDescriptor。因此我们不会去创建一个新的 resourceDescriptor,而使 用这个已存在的resourceDescriptor,并用它的名字作为该resourceInfo的名字, 即新创建的resourceInfo名为:weblogic.jdbc.jta.DataSource。因此3.1.3, 3.1.4步骤不会被执行。
&&&&&&&& &&& 3.2.5:XAServerResourceInfo被创建后,我们会根据 resouceInfo的名字,即 weblogic.jdbc.jta.DataSource, 检查当前tx的 resourceInfoList中是否存在对应的resourceInfo。因为3.1.5结束的时候,我们 已经将一个名为 weblogic.jdbc.jta.DataSource的resourceInfo置入当前tx的 resourceInfoList中,所以这里我们能够找到一个与 weblogic.jdbc.jta.DataSource对应的resourceInfo。因此我们会将这个新创建的 resourceInfo的enlistElseWhere置为true。
&&&&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&& 3.2.6:因为resourceInfo的enlistElseWhere为true, 所以我们 要传递给xaStart的flag为TMJOIN(实际需要的应该是TMNOFALGS),接下来会调用 start(xid, TMJOIN)来通知RESOURCE_MANAGER(Database_B)将当前线程和已有的 transaction branch关联。但Database_B中没有和该global transaction相对应的 transaction branch,所以TMJOIN失败,即如下的错误会被抛出,
&&&&&&&& java.sql.SQLException: Unexpected exception while enlisting XAConnection java.sql.SQLException: XA error: XAER_NOTA : The XID is not valid start() failed on resource 'weblogic.jdbc.jta.DataSource': XAER_NOTA : The XID is not valid
&&&&&&&&&&&&&
&&& 这个问题是weblogic的产品限制,它是WAD(work as design)的,并不是产品bug。在weblogic81sp6中,这种配置会有错误信息输出。&&&&&&&&&&&&&&&&&&&&&
阅读(2591)本帖子已过去太久远了,不再提供回复功能。

我要回帖

更多关于 数据库连接池满了报错 的文章

 

随机推荐