1

Resin + Oracle での XA トランザクションの問題を解決するのを手伝ってくれませんか?

Oracle 11.2.0.1 と Ehcache 2.7 の両方を含むビジネス トランザクションを実行する必要がある WebApp があります。(実際にはさまざまな組み合わせが可能です。Ehcache の有無にかかわらず、2 つの異なる Oracle データ ソース (異なるスキーマ) など)。これが、単純な JDBC の使用から JTA トランザクション境界に切り替える理由でした。

以下を使用します: - Spring 3.2.1 で装飾された樹脂 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。
  • 次のように、resin.conf を介して構成された Oracle ドライバー「oracle.jdbc.xa.client.OracleXADataSource」を使用した樹脂接続プール

    <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. 外側のトランザクションで Ehcache アクセスを行い、内側のトランザクションでのみ DB アクセスを行うことも、内側のトランザクションに REQUIRES_NEW を使用しても問題なく機能します。

  2. 外部トランザクションまたは両方のトランザクションでの DB アクセスの場合 (DataSource の使用がトランザクション境界と重複していなくても、関与する DataSource の数に関係なく)、内部トランザクションのコミットで次のエラーが発生します。

_

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 を呼び出すとエラー コードが返されます)。内部トランザクションのコミット中に何らかの理由でアプリケーションにリソース (DataSource) が含まれているように見えますが、内部トランザクションでデータベースが使用されていないため、Oracle への呼び出しは想定されていないため、これは正しくないようです。

最悪なのは、Resin プール実装の代わりに Apache DBCP プールを使用することで問題が解決することです... Atomikos の使用 (TransactionManager 実装と Connections プール実装の両方) も問題なく動作します。しかし、言及された両方の実装には、独自の問題があります。

現時点では、DB プールまたは XA ドライバーの構成に問題があると思われます。この問題は、グローバルではなくローカル トランザクションを使用するなどの機能強化に関連している可能性がありますか? さまざまなリソース定義 (データベース、resource-ref) を試し、「xa-forbid-same-rm」を使用し、Spring トランザクション同期をオフにし、TransactionManager を手動で使用してトランザクションを一時停止/再開しようとしましたが、すべてうまくいきませんでした。

どんなアイデア/解決策も大歓迎です!

4

1 に答える 1

1

Resin/Spring/Oracle/XA トランザクションの組み合わせは完璧に機能します。ここで重要なことは、DB 接続を正しく処理することです。

すべての DB 接続は、トランザクション内で開く必要があります。この場合、このリソースは暗黙的にトランザクションに登録されます。サンプルコードはそうしています。

問題は、NEW トランザクションの開始時にデータベース接続を OPEN のままにしたことです。これは、Resin の DB プール (別名 UserConnection) によって提供される db 接続が、新しいトランザクションを開始する前にプールに戻されなかったことを意味します。何らかの理由で、Resin TransactionManager の実装は、内部トランザクションで使用されるリソースのリストに UNreturned db 接続を暗黙的に追加しました。また、内部トランザクションのコミットは失敗しました。これは、Oracle がデータベース接続がコミットされていない外部トランザクションで既に使用されていることを認識しているためです。

db 接続を安全にプールに戻すことができます。内部トランザクションの実行後 (樹脂が新しいトランザクション内で新しいデータベース接続を提供するため、コミットされていない変更はすべて表示されません)、外部トランザクションでデータベース接続を再度要求すると、このデータベース接続は内部トランザクションを開始する前のものとまったく同じになります。 、コミットされていないすべての変更が表示されます。したがって、レジンの接続プールから、現在の UserTransaction に関連付けられた接続が提供されます。

もう 1 つ重要なこと - Spring を使用してデータ ソース (DataSourceUtils) から接続を取得する場合、内部トランザクションを開始する前に DataSourceUtils を使用して接続を解放し、Spring に接続が返されたことを知らせる必要があります。実際、Spring のもう 1 つの利点は、独自の追加の 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() を呼び出すと、それがプールに返されるだけです (メソッド名「release」の方がはるかに優れています!)。UserTransaction をアクティブにしても、commit() を明示的に呼び出すまで変更はコミットされません。

助けてくれてありがとう!

于 2013-04-19T16:03:22.917 に答える