首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >控制两阶段提交事务的提交顺序

控制两阶段提交事务的提交顺序
EN

Stack Overflow用户
提问于 2018-03-07 05:18:38
回答 1查看 1.1K关注 0票数 1

我们在WebshereApplicationServer8.5.5上运行了一个java应用程序。有两个进程在单独的JVM中运行。应用程序正在使用和Oracle 11c数据库进行一些集成。JMS和JDBC资源都配置为使用XA事务。

流程1:

  1. 消息队列中读取消息,并提取用于标识相关消息的消息密钥
  2. 将消息保存到数据库。
  3. 检查消息键是否不存在于表中,如果不存在,则将其插入
  4. 只有当上面的插入发生时,它才将消息键放入队列中。
  5. 提交事务

流程2:

  1. 队列中获取消息键。
  2. 表中删除消息键。
  3. 处理来自消息表的与接收到的消息密钥关联的所有消息

我们观察到的是,在大约5%的情况下,在从队列中获取消息密钥后,PROCESS 2有时无法找到要从表中删除的记录,以便在毫秒后变为可用。尝试多次删除它,修复了这个问题,但是很明显,即使启用了PROCESS 1,它也会首先提交JMS资源,然后在很短的时间内提交处于不一致状态的数据。

所以我的问题是:

有没有办法迫使事务管理器先提交JDBC,然后再提交JMS?

我们在IBM知识中心上找到了这一点,并尝试像这样配置提交优先级:

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar-ext xmlns="http://websphere.ibm.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-ejb-jar-ext_1_0.xsd"
         version="1.0">
    <session name="RepositoryInstanceFacade">
        <resource-ref name="jms/MQConnectionFactory" commit-priority="1" isolation-level="TRANSACTION_READ_COMMITTED"/>
        <resource-ref name="jdbc/MessageManagerDB" commit-priority="2" isolation-level="TRANSACTION_READ_COMMITTED"/>
    </session>
</ejb-jar-ext>

然而,这并没有解决我们的问题。我相信我们不是唯一面临这个问题的人,但我只是不知道该怎么做。最后,我们将消息密钥放回队列中,这解决了问题,但在我看来,这是一个非常非正统的工作,而不是一个关键的24x7应用程序的好解决方案。

预先感谢您的投入。

UPDATE我在我的ejb应用程序的META文件夹中添加了这个资源绑定文件IBM-EJB-Ja-bnd.xml,但仍然没有成功。作为部署的一部分,我可以看到IBM操纵该文件并将其转换为XMI文件。

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar-bnd
    xmlns="http://websphere.ibm.com/xml/ns/javaee"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee
     http://websphere.ibm.com/xml/ns/javaee/ibm-ejb-jar-bnd_1_0.xsd" 
    version="1.0">

    <session name="RepositoryInstanceFacade">
        <resource-ref name="jdbc/MessageManagerDB" binding-name="jdbc/MessageManagerDB"/>
    </session>
</ejb-jar-bnd>

UPDATE 2 I在以下两个JVM中进行了配置,每个JVM运行自己的应用程序:

代码语言:javascript
运行
复制
application.xml:

<?xml version="1.0" encoding="UTF-8"?>
<application xmlns="http://java.sun.com/xml/ns/javaee"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/application_6.xsd"
             version="6">
    ...      
    <resource-ref>
        <description>XA Message Manager Data Source</description>
        <res-ref-name>java:app/env/jdbc/MessageManagerDB</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
        <res-sharing-scope>Shareable</res-sharing-scope>
    </resource-ref>
</application>



ibm-aplication-bnd.xml:

    <?xml version="1.0" encoding="UTF-8"?>
<application-bnd
        xmlns="http://websphere.ibm.com/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee
         http://websphere.ibm.com/xml/ns/javaee/ibm-application-bnd_1_0.xsd"
        version="1.0">

    <resource-ref name="java:app/env/jdbc/MessageManagerDB" binding-name="jdbc/MessageManagerDB"/>
</application-bnd>


ibm-ejb-jar-ext.xml:

<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar-ext xmlns="http://websphere.ibm.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-ejb-jar-ext_1_0.xsd"
             version="1.0">
    <session name="RepositoryInstanceFacade">
        <resource-ref name="java:app/env/jdbc/MessageManagerDB" isolation-level="TRANSACTION_READ_COMMITTED" commit-priority="2"/>
    </session>
</ejb-jar-ext>

spring data source bean:

 <jee:jndi-lookup id="messageManagerDB" jndi-name="java:app/env/jdbc/MessageManagerDB"/>

再做一次测试。在测试过程中,我非常高兴,因为日志中没有收到警告消息。然而,给测试运行了几个小时,很难一直手动检查。最后,仍然有三条警告消息显示,在数据库插入可用之前,仍然从队列中读取JMS消息。我还漏掉了什么吗?

注意,我取出了JMS连接工厂的任何设置,因为根据IBM文档,它将保持为零,因此它的提交优先级低于JDBC。

更新3

根据注释和IBM的建议,我最终得到了以下设置:

代码语言:javascript
运行
复制
ejb-jar.xml:
<session name="RepositoryInstanceFacade">
    ...
    <resource-ref>
        <description>XA Message Manager Data Source</description>
        <res-ref-name>jdbc/MessageManagerDB</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
        <res-sharing-scope>Shareable</res-sharing-scope>
    </resource-ref>
</session>

ibm-ejb-jar-bnd.xml:
<resource-ref name="jdbc/MessageManagerDB" binding-name="jdbc/MessageManagerDB"/>

ibm-ejb-jar-ext.xml:
<session name="RepositoryInstanceFacade">
    <resource-ref name="jdbc/MessageManagerDB" isolation-level="TRANSACTION_READ_COMMITTED" commit-priority="2"/>
</session>

spring data source bean:
<jee:jndi-lookup id="messageManagerDB" jndi-name="java:comp/env/jdbc/MessageManagerDB"/>

有了这些设置之后,JMS仍然是先提交的,JDBC是最后提交的,所以它仍然不能像预期的那样工作。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-03-08 16:55:51

根据我在注释中提出的问题,资源引用实际上并没有被用来查找资源,这就是为什么提交优先级属性没有得到遵守的原因。在问题的UPDATE部分,通过为JDBC资源添加资源引用绑定( JMS资源还需要一个等价的),您已经变得更加接近了。您还需要在ejb-jar.xml部署描述符中定义资源引用(如果您愿意的话,也可以定义等价的注释),然后要从应用程序中查找资源,您需要使用名称空间作为资源引用,默认情况下它是java:comp/env,所以您需要将资源查找为java:comp/env/jms/MQConnectionFactory和java:comp/env/jdbc/MessageManagerDB。如果需要组件级别之外的可见性,则可能需要在另一个作用域(如java:module/env或java:app/env )定义,这意味着将资源引用名称更新为相应的值。

UPDATE:使用java:app name的ejb部署描述符/绑定/扩展示例

ejb-jar.xml:

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar xmlns="http://java.sun.com/xml/ns/javaee" version="3.0" metadata-complete="false">
  <enterprise-beans>
    <session>
      <ejb-name>RepositoryInstanceFacade</ejb-name>
      <resource-ref>
        <description>XA Message Manager Data Source</description>
        <res-ref-name>java:app/env/jdbc/MessageManagerDB</res-ref-name>
        <res-type>javax.sql.DataSource</res-type>
        <res-auth>Container</res-auth>
        <res-sharing-scope>Shareable</res-sharing-scope>
      </resource-ref>
    </session>
  </enterprise-beans>
</ejb-jar>

IBMEJBJa-bnd.xml:

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar-bnd xmlns="http://websphere.ibm.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-ejb-jar-bnd_1_0.xsd"
  version="1.0">
  <session name="RepositoryInstanceFacade">
    <resource-ref name="java:app/env/jdbc/MessageManagerDB" binding-name="jdbc/MessageManagerDB"/>
  </session>
</ejb-jar-bnd>

ibm jar-ext.xml:

代码语言:javascript
运行
复制
<?xml version="1.0" encoding="UTF-8"?>
<ejb-jar-ext xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://websphere.ibm.com/xml/ns/javaee"
  xsi:schemaLocation="http://websphere.ibm.com/xml/ns/javaee http://websphere.ibm.com/xml/ns/javaee/ibm-ejb-jar-ext_1_0.xsd"
  version="1.0">
  <session name="RepositoryInstanceFacade">
    <resource-ref name="java:app/env/jdbc/MessageManagerDB" isolation-level="TRANSACTION_READ_COMMITTED" commit-priority="2"/>      
  </session>
</ejb-jar-ext>

用于查找数据源并验证是否使用了来自扩展的隔离级别的应用程序代码:

代码语言:javascript
运行
复制
DataSource ds = InitialContext.doLookup("java:app/env/jdbc/MessageManagerDB");
Connection con = ds.getConnection();
try {
    int iso = con.getTransactionIsolation();
    System.out.println("Isolation level is " + iso);
} finally {
    con.close();
}

如果上面的代码输出2( java.sql.Connection.TRANSACTION_READ_COMMITTED),的值而不是默认的隔离级别4 ),这说明绑定/扩展正在应用。如果在这一点之后,您仍然没有看到提交优先级被执行,那么它就是一个事务管理错误,我建议将它报告给IBM支持部门。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49144625

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档