【问题标题】:Spring XA Transactions With Oracle JDBC Driver使用 Oracle JDBC 驱动程序的 Spring XA 事务
【发布时间】:2011-09-02 08:34:19
【问题描述】:

我正在尝试使用 bitronix 事务管理器启用分布式事务。配置细节包括

  1. 使用 OCI JDBC 驱动程序和 oracle.jdbc.xa.client.OracleXADataSource。此数据源由 UCP 连接池数据源环绕 - oracle.ucp.jdbc.PoolDataSourceImpl
  2. 使用spring JdbcTemplate 执行查询。
  3. 使用 Bitronix 事务管理器处理分布式事务
  4. 使用注解的 Spring 声明式事务

我面临的问题是使用 JDBCTemplate 执行的查询没有在事务中执行。我的测试用例使用 JDBCTemplate 执行两个查询,当方法在查询执行后抛出运行时异常时,它们不会回滚。我还可以看到连接的自动提交状态设置为 true。

<tx:annotation-driven transaction-manager="distributedTransactionManager"/>

<bean id="distributedTransactionManager" class="org.springframework.transaction.jta.JtaTransactionManager">
    <property name="transactionManager" ref="bitronixTransactionManager"/>
    <property name="userTransaction" ref="bitronixTransactionManager"/>
    <property name="allowCustomIsolationLevels" value="true"/>
</bean>

<bean id="bitronixTransactionManager" factory-method="getTransactionManager"
      class="bitronix.tm.TransactionManagerServices" depends-on="bitronixConfiguration"
      destroy-method="shutdown">
</bean>

数据源创建如下

    PoolDataSourceImpl pds = new PoolDataSourceImpl();
    try {
        pds.setConnectionPoolName(dataSourceName);
        pds.setConnectionFactoryClassName("oracle.jdbc.xa.client.OracleXADataSource");
        pds.setConnectionFactoryProperties(getOracleDataSourceProperties());
        pds.setDataSourceName(dataSourceName);
        pds.setServerName("v-in-sd-tst-12");
        pds.setPortNumber(1521);
        pds.setUser("ForTestCasesAmit");
        pds.setPassword("adept");
        pds.setMinPoolSize(10);
        pds.setMaxPoolSize(100);
        pds.setMaxIdleTime(1800);

        pds.startPool();
    } catch (SQLException e) {
        throw new RuntimeException("Cannot create project datasource " + dataSourceName, e);
    }
    return pds;

关于查询未在事务中执行的原因有什么建议?

更新 1

添加使用 jdbcTemplate 执行查询并在最后抛出异常的方法

@Transactional(propagation = Propagation.REQUIRED)
public void execute() {
    System.out.println("Starting with the service method");
    jdbcTemplateForDSOne.update("UPDATE T1 SET COL1 = 'Date1' WHERE COL2 = 1");

    jdbcTemplateForDSOne.update("UPDATE T1 SET COL1 = 'Start Date1' WHERE COL2 = 2");

    waitForUserInput();
    throw new RuntimeException("Rollback Now");
}

更新 2

Oracle JDBC Developer Guide 提到

“在 Oracle Database 10g 之前的所有版本中,从 XAConnection 获得的连接的默认自动提交状态为 false。从 Oracle Database 10g 开始,默认状态为 true。”

我正在使用 Oracle 11g r2。知道在使用分布式事务将自动提交状态设置为 false 时应该进行哪些配置更改吗?

更新 3

如果我使用 bitronix 池数据源而不是 oracle ucp PoolDataSource,则事务可以工作。使用 bitronix PoolingDataSource 使 bitronix 有机会将自动提交状态设置为 false。将进行更多调查以找出两者之间的区别。

【问题讨论】:

    标签: oracle spring jta jdbctemplate oracle-call-interface


    【解决方案1】:

    据我所知,它们是在事务中执行的,但事务不是您所期望的。当autoCommittrue 时,每个查询都成为一个事务。您必须正确配置连接以避免这种情况。

    也就是说,关于 XA 的评论:XA 在网络问题和超时等极端情况下不起作用。也就是说,它会工作 99.9995% 次,但在一些关键情况下,它不会,而这些是您关心的情况。

    确保您的数据结构在 XA 最终失败时不会损坏。

    我建议评估允许再次运行事务的方法,而不是 XA。示例:您想将一些记录从数据库 A 传输到 B。因此您读取带有 FOR UPDATE 的行,并且对于每个传输的行,您将 processed 列设置为 true。

    另一方面,您只添加不存在的行。

    在B中的tx提交后,删除A中的行where processed = 'true'或用其他方式标记。

    这意味着您可以根据需要随时运行它。

    [编辑]

    要禁用自动提交,您必须调用 con.setAutoCommit(false); 当然,问题是您使用的是 Spring,因此您永远不会在任何地方明确请求连接。

    我的建议:扩展PoolDataSourceImpl 并覆盖各种get*Connection() 方法。在返回它们之前,将自动提交设置为 false。您还可以反编译 JDBC 驱动程序代码以查看 PoolDataSourceImpl 是否已经包含类似的内容,但显然没有。

    【讨论】:

    • 好的。您是否有建议/原因为什么即使应用了事务也不会回滚这两个查询?更重要的是,当抛出运行时异常时,我应该进行哪些配置更改才能回滚?
    • 因为在您发出commit 后不会发生回滚。会发生什么是q1; commit; q2; commit; throw exception; rollback。要更改 autoCommit,请检查创建连接的代码。在你的情况下,PoolDataSourceImpl 应该有一个方法。
    • 是的。我知道自动提交设置为 true,因此不会发生回滚。我提出这个问题的目的是想知道是否有人尝试使用具有上述配置的分布式事务以及我缺少哪些更详细的细节。
    • 没有一种事务框架适用于自动提交 == true。 Auto commit == true 表示每次查询后,驱动程序将发送commit 到数据库。应该很明显为什么这会干扰试图推动提交的框架。
    • 我没完全明白你想说什么。我的想法是我缺少一些配置设置,这就是我试图通过发布这个问题来解决的问题。你是说配置中没有更多的东西了?
    【解决方案2】:

    您是否有包含此代码的方法,使用 @Transactional 注释或定义了任何可以告诉 Spring 在事务中执行此方法的 Aspects?

    【讨论】:

    • 我已经用spring注解的方法更新了问题。
    猜你喜欢
    • 1970-01-01
    • 2013-08-12
    • 2012-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多