【问题标题】:Resin + Oracle + [Spring] + XA Transaction REQUIRES_NEW – Inner Transaction Commit FailsResin + Oracle + [Spring] + XA 事务 REQUIRES_NEW – 内部事务提交失败
【发布时间】:2013-04-11 21:23:11
【问题描述】:

能否请您帮忙解决 Resin + Oracle 上的 XA 事务问题:

我们有 WebApp,它必须执行涉及 Oracle 11.2.0.1 和 Ehcache 2.7 的业务事务。 (实际上可能有各种组合——两个不同的 Oracle 数据源(不同的模式)有/没有 Ehcache 等)。这就是从普通 JDBC 使用切换到 JTA 事务划分的原因。

我们使用: - 使用 Spring 3.2.1 装饰的 Resin JTA 实现,以简化事务暂停并利用程序化方法定义事务边界(“手动”使用 TransactionManager 来暂停/恢复也会产生问题),如下所示:

public void doOuterTransaction() throws Throwable {
    DefaultTransactionDefinition def = new DefaultTransactionDefinition();
    def.setName("myTx");
    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES);
    TransactionStatus status = txManager.getTransaction(def);
    Connection connection = null;
    Cache cache = null;
    try {
        cache = ...; // get cache from CacheManager
        connection = myDataSource.getConnection(); // or "DataSourceUtils.getConnection(myDataSource)" to guarantee same dbConnection from Spring
        // some business logic
        doInnerTransaction();
        // some business logic
        txManager.commit(status);
    } catch (Throwable ex) {
        txManager.rollback(status);
        throw ex;
    } finally {
        if (connection!=null) {
            connection.close();
        }
    }
}

public void doInnerTransaction() throws Throwable {
    DefaultTransactionDefinition def = new DefaultTransactionDefinition();
    def.setName("myTx");
    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
    TransactionStatus status = txManager.getTransaction(def);
    Connection connection = null;
    Cache cache = null;
    try {
        cache = ...; // get cache from CacheManager
        connection = myDataSource.getConnection(); // or "DataSourceUtils.getConnection(myDataSource)" to guarantee same dbConnection from Spring
        // some business logic
        txManager.commit(status);
    } catch (Throwable ex) {
        txManager.rollback(status);
        throw ex;
    } finally {
        if (connection!=null) {
            connection.close();
        }
    }
}
  • 带有配置了“XA”事务支持的缓存的 Ehcache。
  • 带有Oracle驱动“oracle.jdbc.xa.client.OracleXADataSource”的Resin连接池,通过resin.conf配置如下

    <database>
    <name>my_xa_datasource</name>
    <jndi-name>jdbc/my_xa</jndi-name>
    <driver>
        <type>oracle.jdbc.xa.client.OracleXADataSource</type>
        <url>${MY_DB_URL}</url>
        <user>${MY_DB_USERNAME}</user>
        <password>${MY_DB_PASSWORD}</password>
    </driver>
    <max-connections>50</max-connections>
    <max-idle-time>60s</max-idle-time>
    <max-active-time>24h</max-active-time>
    <max-overflow-connections>15</max-overflow-connections>
    <ping>true</ping>
    <ping-table>DUAL</ping-table>
    <ping-interval>240s</ping-interval>
    <transaction-timeout>24h</transaction-timeout>
    <xa>true</xa>
    </database>
    

具有传播级别 REQUIRED 的任何受影响资源组合的所有事务开箱即可正常工作。但是当我们遇到外部事务“REQUIRED”和内部事务“REQUIRES_NEW”的情况时——暂停外部事务会导致问题,内部事务无法提交。甚至更多 - 已经在运行内部事务,我们可以看到来自外部事务的未提交更改,这看起来完全错误。

行为取决于外部和内部事务涉及哪些资源。我们有以下案例: 1. 在内部和外部事务中只有 Ehcache 访问可以正常工作,即使内部事务使用 REQUIRES_NEW。

  1. 即使内部事务使用 REQUIRES_NEW,在外部事务中访问 Ehcache 并在内部事务中仅访问 DB 也可以正常工作。

  2. 在外部事务或两个事务中访问数据库的情况(无论涉及多少数据源,即使数据源的使用不与事务边界重叠)在提交内部事务时会出现以下错误:

_

ch.sc.common.ShortAGRuntimeException: org.springframework.transaction.TransactionSystemException:
JTA failure on commit; nested exception is com.caucho.transaction.SystemExceptionWrapper:
XA_RMERR: Resource manager error.
at ch.sc.glibs.mytest.MyTestServlet.doGet(MyTestServlet.java:34)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:120)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:97)
at com.caucho.server.dispatch.ServletFilterChain.doFilter(ServletFilterChain.java:109)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at com.caucho.server.security.SecurityFilterChain.doFilter(SecurityFilterChain.java:132)
at com.caucho.server.webapp.WebAppListenerFilterChain.doFilter(WebAppListenerFilterChain.java:114)
at com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:156)
at com.caucho.server.webapp.AccessLogFilterChain.doFilter(AccessLogFilterChain.java:95)
at com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:289)
at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:838)
at com.caucho.network.listen.TcpSocketLink.dispatchRequest(TcpSocketLink.java:1309)
at com.caucho.network.listen.TcpSocketLink.handleRequest(TcpSocketLink.java:1265)
at com.caucho.network.listen.TcpSocketLink.handleRequestsImpl(TcpSocketLink.java:1249)
at com.caucho.network.listen.TcpSocketLink.handleRequests(TcpSocketLink.java:1157)
at com.caucho.network.listen.TcpSocketLink.handleAcceptTaskImpl(TcpSocketLink.java:956)
at com.caucho.network.listen.ConnectionTask.runThread(ConnectionTask.java:117)
at com.caucho.network.listen.ConnectionTask.run(ConnectionTask.java:93)
at com.caucho.network.listen.SocketLinkThreadLauncher.handleTasks(SocketLinkThreadLauncher.java:169)
at com.caucho.network.listen.TcpSocketAcceptThread.run(TcpSocketAcceptThread.java:61)
at com.caucho.env.thread2.ResinThread2.runTasks(ResinThread2.java:173)
at com.caucho.env.thread2.ResinThread2.run(ResinThread2.java:118)
Caused by: org.springframework.transaction.TransactionSystemException:
JTA failure on commit; nested exception is com.caucho.transaction.SystemExceptionWrapper:
XA_RMERR: Resource manager error.
at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1025)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at ch.sc.glibs.mytest.MyTxTest.test3(MyTxTest.java:155)
at ch.sc.glibs.mytest.MyTxTest.doMainComplexTx(MyTxTest.java:81)
at ch.sc.glibs.mytest.MyTxTest.doTxTest(MyTxTest.java:50)
at ch.sc.glibs.mytest.MyTxTest__ResinScopeProxy.doTxTest(Unknown Source)
at ch.sc.glibs.mytest.MyTestServlet.doGet(MyTestServlet.java:32)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:120)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:97)
at com.caucho.server.dispatch.ServletFilterChain.doFilter(ServletFilterChain.java:109)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at com.caucho.server.security.SecurityFilterChain.doFilter(SecurityFilterChain.java:132)
at com.caucho.server.webapp.WebAppListenerFilterChain.doFilter(WebAppListenerFilterChain.java:114)
at com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:156)
at com.caucho.server.webapp.AccessLogFilterChain.doFilter(AccessLogFilterChain.java:95)
at com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:289)
at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:838)
at com.caucho.network.listen.TcpSocketLink.dispatchRequest(TcpSocketLink.java:1309)
at com.caucho.network.listen.TcpSocketLink.handleRequest(TcpSocketLink.java:1265)
at com.caucho.network.listen.TcpSocketLink.handleRequestsImpl(TcpSocketLink.java:1249)
at com.caucho.network.listen.TcpSocketLink.handleRequests(TcpSocketLink.java:1157)
at com.caucho.network.listen.TcpSocketLink.handleAcceptTaskImpl(TcpSocketLink.java:956)
at com.caucho.network.listen.ConnectionTask.runThread(ConnectionTask.java:117)
at com.caucho.network.listen.ConnectionTask.run(ConnectionTask.java:93)
at com.caucho.network.listen.SocketLinkThreadLauncher.handleTasks(SocketLinkThreadLauncher.java:169)
at com.caucho.network.listen.TcpSocketAcceptThread.run(TcpSocketAcceptThread.java:61)
at com.caucho.env.thread2.ResinThread2.runTasks(ResinThread2.java:173)
at com.caucho.env.thread2.ResinThread2.run(ResinThread2.java:118)
Caused by: com.caucho.transaction.SystemExceptionWrapper: XA_RMERR: Resource
manager error.
at com.caucho.transaction.TransactionImpl.heuristicException(TransactionImpl.java:1040)
at com.caucho.transaction.TransactionImpl.commitResources(TransactionImpl.java:931)
at com.caucho.transaction.TransactionImpl.commit(TransactionImpl.java:886)
at com.caucho.transaction.TransactionManagerImpl.commit(TransactionManagerImpl.java:324)
at com.caucho.transaction.UserTransactionImpl.commit(UserTransactionImpl.java:363)
at com.caucho.transaction.UserTransactionProxy.commit(UserTransactionProxy.java:171)
at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1009)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at ch.sc.glibs.mytest.MyTxTest.test3(MyTxTest.java:155)
at ch.sc.glibs.mytest.MyTxTest.doMainComplexTx(MyTxTest.java:81)
at ch.sc.glibs.mytest.MyTxTest.doTxTest(MyTxTest.java:50)
at ch.sc.glibs.mytest.MyTxTest__ResinScopeProxy.doTxTest(Unknown Source)
at ch.sc.glibs.mytest.MyTestServlet.doGet(MyTestServlet.java:32)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:120)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:97)
at com.caucho.server.dispatch.ServletFilterChain.doFilter(ServletFilterChain.java:109)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at com.caucho.server.security.SecurityFilterChain.doFilter(SecurityFilterChain.java:132)
at com.caucho.server.webapp.WebAppListenerFilterChain.doFilter(WebAppListenerFilterChain.java:114)
at com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:156)
at com.caucho.server.webapp.AccessLogFilterChain.doFilter(AccessLogFilterChain.java:95)
at com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:289)
at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:838)
at com.caucho.network.listen.TcpSocketLink.dispatchRequest(TcpSocketLink.java:1309)
at com.caucho.network.listen.TcpSocketLink.handleRequest(TcpSocketLink.java:1265)
at com.caucho.network.listen.TcpSocketLink.handleRequestsImpl(TcpSocketLink.java:1249)
at com.caucho.network.listen.TcpSocketLink.handleRequests(TcpSocketLink.java:1157)
at com.caucho.network.listen.TcpSocketLink.handleAcceptTaskImpl(TcpSocketLink.java:956)
at com.caucho.network.listen.ConnectionTask.runThread(ConnectionTask.java:117)
at com.caucho.network.listen.ConnectionTask.run(ConnectionTask.java:93)
at com.caucho.network.listen.SocketLinkThreadLauncher.handleTasks(SocketLinkThreadLauncher.java:169)
at com.caucho.network.listen.TcpSocketAcceptThread.run(TcpSocketAcceptThread.java:61)
at com.caucho.env.thread2.ResinThread2.runTasks(ResinThread2.java:173)
at com.caucho.env.thread2.ResinThread2.run(ResinThread2.java:118)
Caused by: oracle.jdbc.xa.OracleXAException
at oracle.jdbc.xa.OracleXAResource.checkError(OracleXAResource.java:1110)
at oracle.jdbc.xa.client.OracleXAResource.end(OracleXAResource.java:436)
at com.caucho.sql.DisjointXAResource.end(DisjointXAResource.java:105)
at com.caucho.env.dbpool.ManagedPoolItem.endResource(ManagedPoolItem.java:1017)
at com.caucho.env.dbpool.ManagedPoolItem.commit(ManagedPoolItem.java:957)
at com.caucho.transaction.TransactionImpl.commitResources(TransactionImpl.java:924)
at com.caucho.transaction.TransactionImpl.commit(TransactionImpl.java:886)
at com.caucho.transaction.TransactionManagerImpl.commit(TransactionManagerImpl.java:324)
at com.caucho.transaction.UserTransactionImpl.commit(UserTransactionImpl.java:363)
at com.caucho.transaction.UserTransactionProxy.commit(UserTransactionProxy.java:171)
at org.springframework.transaction.jta.JtaTransactionManager.doCommit(JtaTransactionManager.java:1009)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
at ch.sc.glibs.mytest.MyTxTest.test3(MyTxTest.java:155)
at ch.sc.glibs.mytest.MyTxTest.doMainComplexTx(MyTxTest.java:81)
at ch.sc.glibs.mytest.MyTxTest.doTxTest(MyTxTest.java:50)
at ch.sc.glibs.mytest.MyTxTest__ResinScopeProxy.doTxTest(Unknown Source)
at ch.sc.glibs.mytest.MyTestServlet.doGet(MyTestServlet.java:32)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:120)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:97)
at com.caucho.server.dispatch.ServletFilterChain.doFilter(ServletFilterChain.java:109)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at ch.sc.common.http.filters.RegexpFilteringProxyFilter.doFilter(RegexpFilteringProxyFilter.java:65)
at com.caucho.server.dispatch.FilterFilterChain.doFilter(FilterFilterChain.java:89)
at com.caucho.server.security.SecurityFilterChain.doFilter(SecurityFilterChain.java:132)
at com.caucho.server.webapp.WebAppListenerFilterChain.doFilter(WebAppListenerFilterChain.java:114)
at com.caucho.server.webapp.WebAppFilterChain.doFilter(WebAppFilterChain.java:156)
at com.caucho.server.webapp.AccessLogFilterChain.doFilter(AccessLogFilterChain.java:95)
at com.caucho.server.dispatch.ServletInvocation.service(ServletInvocation.java:289)
at com.caucho.server.http.HttpRequest.handleRequest(HttpRequest.java:838)
at com.caucho.network.listen.TcpSocketLink.dispatchRequest(TcpSocketLink.java:1309)
at com.caucho.network.listen.TcpSocketLink.handleRequest(TcpSocketLink.java:1265)
at com.caucho.network.listen.TcpSocketLink.handleRequestsImpl(TcpSocketLink.java:1249)
at com.caucho.network.listen.TcpSocketLink.handleRequests(TcpSocketLink.java:1157)
at com.caucho.network.listen.TcpSocketLink.handleAcceptTaskImpl(TcpSocketLink.java:956)
at com.caucho.network.listen.ConnectionTask.runThread(ConnectionTask.java:117)
at com.caucho.network.listen.ConnectionTask.run(ConnectionTask.java:93)
at com.caucho.network.listen.SocketLinkThreadLauncher.handleTasks(SocketLinkThreadLauncher.java:169)
at com.caucho.network.listen.TcpSocketAcceptThread.run(TcpSocketAcceptThread.java:61)
at com.caucho.env.thread2.ResinThread2.runTasks(ResinThread2.java:173)
at com.caucho.env.thread2.ResinThread2.run(ResinThread2.java:118)

在内部,我们在准备提交阶段看到 ORA-25352“无当前事务”“用户会话未附加到任何事务”(调用 Oracle JAVA_XA.prepare 返回错误代码)。 看起来好像在内部事务提交应用程序期间由于某种原因涉及外部事务中受影响的资源(数据源),这似乎是不正确的,因为在内部事务中没有使用数据库,我们预计不会调用 Oracle。

最糟糕的是,使用 Apache DBCP 池而不是 Resin 池实现解决了问题……使用 Atomikos(TransactionManager 实现和 Connections Pool 实现)也可以正常工作。但上述两种实现都有各自的问题。

目前我们假设我们遇到了 DB 池或 XA 驱动程序配置问题…… 该问题是否与使用本地事务而不是全局事务等任何增强功能相关联? 我们尝试了各种资源定义(数据库、资源引用),使用了“xa-forbid-same-rm”,关闭了 spring 事务同步,尝试手动使用 TransactionManager 来暂停/恢复事务等等 - 一切都没有运气。

欢迎任何想法/解决方案!

【问题讨论】:

    标签: oracle datasource spring-transactions distributed-transactions resin


    【解决方案1】:

    Resin/Spring/Oracle/XA Transactions 组合完美运行。 这里的关键是正确使用数据库连接。

    所有数据库连接都必须在您的事务内部打开。在这种情况下,该资源将被隐式地征入事务。 我们的示例代码就是这样做的。

    问题是我们在启动新事务时打开了数据库连接。这意味着 Resin 的数据库池(又名 UserConnection)提供的数据库连接在开始新事务之前没有返回到池中。 由于某种原因,Resin TransactionManager 实现隐式地将 UNreturned db 连接添加到内部事务中使用的资源列表中。并且内部事务的提交失败,因为Oracle知道数据库连接已经在外部未提交的事务中使用。

    可以安全地将数据库连接返回到池中。执行内部事务后(由于树脂会在新事务中为您提供新的数据库连接,因此看不到所有未提交的更改)您可能会再次要求外部事务中的数据库连接,此数据库连接将与开始内部事务之前的完全相同,因此您将看到所有未提交的更改。因此,将从树脂的连接池中提供与当前 UserTransaction 关联的连接。

    更重要的一点 - 如果您使用 Spring 从数据源 (DataSourceUtils) 获取连接,则必须在开始内部事务之前使用 DataSourceUtils 释放连接,以让 Spring 知道连接已返回。实际上 Spring 的另一个优点是您可以拥有自己的附加 TransactionSynchronization 逻辑。 您也可以直接使用数据源(不使用 Spring),在这种情况下,您可以调用 connection.close() 将其返回到连接池。

    最后外部交易(任何交易)的代码应该是这样的:

    public void doOuterTransaction() throws Throwable {
        DefaultTransactionDefinition def = new DefaultTransactionDefinition();
        def.setName("myTx");
        def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES);
        TransactionStatus status = txManager.getTransaction(def);
        Connection connection = null;
        Cache cache = null;
        try {
            try {
                cache = ...; // get cache from CacheManager
                connection = DataSourceUtils.getConnection(myDataSource);
                // some business logic
            } finally {
                DataSourceUtils.releaseConnection(connection, myDataSource);
            }
    
            doInnerTransaction();
    
            try {
                cache = ...; // get cache from CacheManager
                connection = DataSourceUtils.getConnection(myDataSource);
                // some other business logic 
            } finally {
                DataSourceUtils.releaseConnection(connection, myDataSource);
            }
        } catch (Throwable ex) {
            txManager.rollback(status);
            throw ex;
        }
    
        txManager.commit(status);
    }
    

    所以不要害怕获取和释放数据库连接。你有连接池 - 它很快。在连接上调用 close() 只会将其返回到池中(方法名称“释放”要好得多!)。在您明确调用 commit() 之前,拥有活动的 UserTransaction 不会提交您的更改。

    感谢大家的帮助!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-10-25
      • 2012-10-14
      • 2017-11-21
      • 2020-06-23
      • 2014-04-16
      • 1970-01-01
      • 2014-03-16
      相关资源
      最近更新 更多