1

Не могли бы вы помочь решить проблему с XA сделок на Ресина + Oracle:смола + Oracle + [Весна] + XA транзакции REQUIRES_NEW - Внутренняя транзакции Сбой

Мы имеем WebApp, который имеет для выполнения бизнес-операций, которые включают как Oracle 11.2.0.1, так и Ehcache 2.7. (На самом деле возможны различные комбинации - два разных источника данных Oracle (разные схемы) с/без Ehcache и т. Д.). Это стало причиной перехода от простого использования JDBC к демаркации транзакций JTA.

Мы используем: - Реализация смолы JTA, которая украшена весной 3.2.1, для упрощения транзакций, приостанавливающих и использующих программный подход к определению границ транзакций («ручное» использование 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(); 
     } 
    } 
} 
  • Ehcache с кэшей, сконфигурированных с поддержкой «ХА» сделок.
  • соединения смолы бассейн с водителем Oracle «oracle.jdbc.xa.client.OracleXADataSource» настраивался через 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> 
    

Все операции с любой комбинацией затронутых ресурсов с уровнем распространения ТРЕБУЕТСЯ работает отлично. Но когда мы имеем дело с внешней транзакцией «ТРЕБУЕМАЯ» и внутренней транзакцией «REQUIRES_NEW» - приостановка внешней транзакции вызывает проблемы и внутренняя транзакция не может быть выполнена. И даже больше - уже выполняющаяся внутренняя транзакция, мы можем видеть, что UNcommited изменения из внешней транзакции выглядят совершенно неправильно.

Поведение зависит от того, какие ресурсы задействованы во внешних и внутренних транзакциях. У нас есть следующие случаи: 1. Доступ только к Ehcache как в внутренних, так и в внешних транзакциях работает нормально даже с REQUIRES_NEW для внутреннего.

  1. Имея доступ Ehcache в внешней транзакции и доступ к БД только во внутренней транзакции также отлично работает даже с REQUIRES_NEW для внутреннего.

  2. Случай с доступом БД в внешней транзакции или в обеих сделках (независимо от того, сколько DataSources вовлечены, даже если использование DataSources не перекрывает границы транзакции) дает следующее сообщение об ошибке с фиксации внутренней транзакции:

_

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 возвращает C ошибку ода). Похоже, что во время внутреннего приложения фиксации транзакции по какой-либо причине задействованы ресурсы (DataSource), затронутые во внешней транзакции, которые кажутся неправильными, потому что без использования db во внутренней транзакции мы не ожидаем вызова Oracle.

Хуже всего то, что использование пула Apache DBCP вместо реализации пула Resin SOLVES вызывает проблему ... Использование Atomikos (как реализации TransactionManager, так и реализации пулов соединений) также отлично работает. Но обе упомянутые реализации имеют свою проблему.

На данный момент мы предполагаем, что у нас возникли проблемы с конфигурацией пула БД или XA ... Может ли проблема быть связана с любыми улучшениями, такими как использование локальных транзакций вместо глобальных и т. Д.? Мы попробовали определение различных ресурсов (база данных, ресурс-ref), использовали «xa-forbid-same-rm», отключили синхронизацию пружинных транзакций, попытались вручную использовать TransactionManager, чтобы приостановить/возобновить транзакцию и т. Д. - все без везения.

Любые идеи и решения приветствуются!

ответ

1

Комбинированная смола/весна/Oracle/XA Transactions работает отлично. Главное здесь - правильно работать с соединениями DB.

Все подключения к БД должны быть открыты ВНУТРИ вашей транзакции. В этом случае этот ресурс будет зачислен на транзакцию неявно. Наш пример кода делает это.

Проблема была в том, что мы покинули соединение db OPEN при запуске новой транзакции. Это означает, что соединение db, предоставленное пулом базы данных Resin (aka UserConnection), не было возвращено в пул перед началом новой транзакции. По какой-то причине реализация Resin TransactionManager добавила невозвращенное соединение Db в список ресурсов, используемых во внутренней транзакции. И фиксация внутренней транзакции завершилась неудачно, поскольку Oracle знает, что соединение db уже используется во внешней незафиксированной транзакции.

Можно безопасно вернуть соединение db к бассейну. После выполнения внутренней транзакции (когда все незафиксированные изменения не видны, потому что смола предоставит вам новое соединение db внутри новой транзакции), вы можете снова запросить соединение db во внешней транзакции, и это соединение db будет точно таким же, как и перед началом внутренней транзакции , поэтому вы увидите все свои незафиксированные изменения. Таким образом, из пула соединений смолы будет предоставлено соединение, связанное с текущим UserTransaction.

Еще одна важная вещь: если вы используете Spring для подключения к источнику данных (DataSourceUtils), вы ДОЛЖНЫ использовать DataSourceUtils для освобождения соединения перед началом внутренних транзакций, чтобы Spring знал, что соединение было возвращено. На самом деле еще одно преимущество Spring заключается в том, что у вас может быть ваша дополнительная логика TransactionSynchronization. Вы также можете использовать источник данных напрямую (без пружины), и в этом случае вы можете вызвать 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().

Спасибо всем за помощь!

Смежные вопросы