Spring + Hibernate + DB2 + JTA + XA应用程序中的死锁


问题内容

应用程序日志中的异常:

12:04:18,503  INFO ExceptionResolver:30 -  [ org.springframework.dao.DeadlockLoserDataAccessException ] Hibernate flushing: could not update: [sero.chase.integration.Beans.Bean#1000]; SQL [update SCHM.v***240u_bean set prop1=?, prop2=?, prop3=?, prop4=?, prop5=?, prop6=?, prop7=?, prop8=?, prop9=?, prop10=?, prop11=?, prop12=?, prop13=?, prop14=?, prop15=?, prop16=?, prop17=?, prop18=?, prop19=?, prop20=?, prop21=?, where bean_id=?]; UNSUCCESSFUL EXECUTION CAUSED BY DEADLOCK OR TIMEOUT. REASON CODE 00C90088, TYPE OF RESOURCE 00000302, AND RESOURCE NAME SCHM.SAKT240 .X'000017'. SQLCODE=-913, SQLSTATE=57033, DRIVER=3.53.70; nested exception is com.ibm.db2.jcc.b.SqlException: UNSUCCESSFUL EXECUTION CAUSED BY DEADLOCK OR TIMEOUT. REASON CODE 00C90088, TYPE OF RESOURCE 00000302, AND RESOURCE NAME SCHM.SAKT240 .X'000017'. SQLCODE=-913, SQLSTATE=57033, DRIVER=3.53.70org.springframework.dao.DeadlockLoserDataAccessException: Hibernate flushing: could not update: [sero.chase.integration.Beans.Bean#1000]; SQL [update SCHM.v***240u_bean set prop1=?, prop2=?, prop3=?, prop4=?, prop5=?, prop6=?, prop7=?, prop8=?, prop9=?, prop10=?, prop11=?, prop12=?, prop13=?, prop14=?, prop15=?, prop16=?, prop17=?, prop18=?, prop19=?, prop20=?, prop21=?, where bean_id=?]; UNSUCCESSFUL EXECUTION CAUSED BY DEADLOCK OR TIMEOUT. REASON CODE 00C90088, TYPE OF RESOURCE 00000302, AND RESOURCE NAME SCHM.SAKT240 .X'000017'. SQLCODE=-913, SQLSTATE=57033, DRIVER=3.53.70; nested exception is com.ibm.db2.jcc.b.SqlException: UNSUCCESSFUL EXECUTION CAUSED BY DEADLOCK OR TIMEOUT. REASON CODE 00C90088, TYPE OF RESOURCE 00000302, AND RESOURCE NAME MWIAKT1 .SAKT240 .X'000017'. SQLCODE=-913, SQLSTATE=57033, DRIVER=3.53.70
    at org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:265)
    at org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72)
    at org.springframework.orm.hibernate3.HibernateTransactionManager.convertJdbcAccessException(HibernateTransactionManager.java:805)
    at org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:791)
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:664)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202)
    at $Proxy54.save(Unknown Source)
    at sero.chase.integration.DaoImpl.ExampleDaoImpl.save(ExampleDaoImpl.java:151)
    at sero.chase.business.BOImpl.ExampleBOImpl.save(ExampleBOImpl.java:191)
    at sero.chase.ServicesImpl.ExampleServiceImpl.submitAnswer(ExampleServiceImpl.java:183)
    at sero.chase.business.BusDelegatesImpl.ExampleBusDelegateImpl.gradeAnswer(ExampleBusDelegateImpl.java:578)
    at sero.chase.presentation.Controller.ExampleController.gradeAnswer(ExampleController.java:326)
    at sero.chase.presentation.Controller.ExampleController.SubmitAnswer(ExampleController.java:422)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:79)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:618)
    at org.springframework.web.servlet.mvc.multiaction.MultiActionController.invokeNamedMethod(MultiActionController.java:471)
    at org.springframework.web.servlet.mvc.multiaction.MultiActionController.handleRequestInternal(MultiActionController.java:408)
    at org.springframework.web.servlet.mvc.AbstractController.handleRequest(AbstractController.java:153)
    at org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter.handle(SimpleControllerHandlerAdapter.java:48)
    at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:900)
    at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:827)
    at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
    at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:763)
    at javax.servlet.http.HttpServlet.service(HttpServlet.java:856)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1152)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.service(ServletWrapper.java:1087)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain.doFilter(WebAppFilterChain.java:118)
    at com.ibm.ws.webcontainer.filter.WebAppFilterChain._doFilter(WebAppFilterChain.java:87)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:840)
    at com.ibm.ws.webcontainer.filter.WebAppFilterManager.doFilter(WebAppFilterManager.java:683)
    at com.ibm.ws.webcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:589)
    at com.ibm.ws.wswebcontainer.servlet.ServletWrapper.handleRequest(ServletWrapper.java:534)
    at com.ibm.ws.webcontainer.servlet.CacheServletWrapper.handleRequest(CacheServletWrapper.java:90)
    at com.ibm.ws.webcontainer.WebContainer.handleRequest(WebContainer.java:751)
    at com.ibm.ws.wswebcontainer.WebContainer.handleRequest(WebContainer.java:1478)
    at com.ibm.ws.webcontainer.channel.WCChannelLink.ready(WCChannelLink.java:126)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleDiscrimination(HttpInboundLink.java:458)
    at com.ibm.ws.http.channel.inbound.impl.HttpInboundLink.handleNewInformation(HttpInboundLink.java:387)
    at com.ibm.ws.http.channel.inbound.impl.HttpICLReadCallback.complete(HttpICLReadCallback.java:102)
    at com.ibm.ws.tcp.channel.impl.AioReadCompletionListener.futureCompleted(AioReadCompletionListener.java:165)
    at com.ibm.io.async.AbstractAsyncFuture.invokeCallback(AbstractAsyncFuture.java:217)
    at com.ibm.io.async.AsyncChannelFuture.fireCompletionActions(AsyncChannelFuture.java:161)
    at com.ibm.io.async.AsyncFuture.completed(AsyncFuture.java:136)
    at com.ibm.io.async.ResultHandler.complete(ResultHandler.java:196)
    at com.ibm.io.async.ResultHandler.runEventProcessingLoop(ResultHandler.java:751)
    at com.ibm.io.async.ResultHandler$2.run(ResultHandler.java:881)
    at com.ibm.ws.util.ThreadPool$Worker.run(ThreadPool.java:1497)
Caused by: com.ibm.db2.jcc.b.SqlException: UNSUCCESSFUL EXECUTION CAUSED BY DEADLOCK OR TIMEOUT. REASON CODE 00C90088, TYPE OF RESOURCE 00000302, AND RESOURCE NAME MWIAKT1 .SAKT240 .X'000017'. SQLCODE=-913, SQLSTATE=57033, DRIVER=3.53.70
    at com.ibm.db2.jcc.b.bd.a(bd.java:679)
    at com.ibm.db2.jcc.b.bd.a(bd.java:60)
    at com.ibm.db2.jcc.b.bd.a(bd.java:127)
    at com.ibm.db2.jcc.b.fm.b(fm.java:2132)
    at com.ibm.db2.jcc.b.fm.c(fm.java:2115)
    at com.ibm.db2.jcc.t4.db.k(db.java:353)
    at com.ibm.db2.jcc.t4.db.a(db.java:59)
    at com.ibm.db2.jcc.t4.t.a(t.java:50)
    at com.ibm.db2.jcc.t4.tb.b(tb.java:200)
    at com.ibm.db2.jcc.b.gm.Zb(gm.java:2445)
    at com.ibm.db2.jcc.b.gm.e(gm.java:3287)
    at com.ibm.db2.jcc.b.gm.Rb(gm.java:612)
    at com.ibm.db2.jcc.b.gm.executeUpdate(gm.java:595)
    at com.ibm.ws.rsadapter.jdbc.WSJdbcPreparedStatement.executeUpdate(WSJdbcPreparedStatement.java:768)
    at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:23)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2399)
    at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2303)
    at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2603)
    at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:92)
    at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:248)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:232)
    at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:140)
    at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:298)
    at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)
    at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1000)
    at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:338)
    at org.hibernate.transaction.JTATransaction.commit(JTATransaction.java:135)
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656)
    ... 50 more

弹簧配置:

<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
    xmlns:jee="http://www.springframework.org/schema/jee" 
    xmlns:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/beans         
                           http://www.springframework.org/schema/beans/spring-beans-3.0.xsd         
                           http://www.springframework.org/schema/context         
                           http://www.springframework.org/schema/context/spring-context-3.0.xsd
                           http://www.springframework.org/schema/jee
                           http://www.springframework.org/schema/jee/spring-jee-3.0.xsd">

    <jee:jndi-lookup id="queueConFac" resource-ref="true" jndi-name="jms/queueConFac" />
    <jee:jndi-lookup id="receiveQ" resource-ref="true" jndi-name="jms/receiveQ" />
    <jee:jndi-lookup id="sendQ" resource-ref="true" jndi-name="jms/sendQ" />
    <jee:jndi-lookup id="XA" resource-ref="true" jndi-name="jdbc/XA" />
    <jee:jndi-lookup id="nonXA" resource-ref="true" jndi-name="jdbc/nonXA" />


    <bean id="jmsTxManager"
    class="org.springframework.transaction.jta.WebSphereUowTransactionManager"/>

    <bean id="jmsDestResolver" class=" org.springframework.jms.support.destination.JndiDestinationResolver"/>

    <bean id="exampleListener" class="sero.chase.integration.JMS.Services.JMSReceiver">
        <property name="exampleAppBusDelegate" ref="exampleAppBusDelegate" />
    </bean>

    <bean class="org.springframework.jms.listener.DefaultMessageListenerContainer" >
        <property name="connectionFactory" ref="queueConFac" />
        <property name="destination" ref="receiveQ" />
        <property name="messageListener" ref="exampleListener" />
        <property name="transactionManager" ref="jmsTxManager" />
        <property name="taskExecutor" ref="jmsTaskExecutor" />
    </bean>

    <bean id="jmsTaskExecutor"
      class="org.springframework.scheduling.commonj.WorkManagerTaskExecutor">
      <property name="workManagerName" value="wm/default" />
   </bean>

   <bean id="jmsSender" class="sero.chase.integration.JMS.Services.JMSSender">
        <property name="connectionFactory" ref="queueConFac" />
        <property name="queue" ref="sendQ" />
    </bean>

    <bean id="localeResolver"
        class="org.springframework.web.servlet.i18n.SessionLocaleResolver">
        <property name="defaultLocale" value="en" />
    </bean>

    <bean id="localeChangeInterceptor"
        class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
        <property name="paramName" value="language" />
    </bean>

    <bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping" >
        <property name="interceptors">
            <list>
                <ref bean="localeChangeInterceptor" />
            </list>
        </property>
    </bean>

    <bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <property name="basename" value="WEB-INF/resources/langSpecificText"/>
    </bean>

    <bean id="viewResolver"
        class="org.springframework.web.servlet.view.UrlBasedViewResolver">
        <property name="viewClass"
            value="org.springframework.web.servlet.view.tiles2.TilesView" />
    </bean>

    <bean id="tilesConfigurer"
        class="org.springframework.web.servlet.view.tiles2.TilesConfigurer">
        <property name="definitions">
            <list>
                <value>/WEB-INF/tiles-def.xml</value>
            </list>
        </property>
    </bean>

    <bean id="dataSource" class="org.springframework.jndi.JndiObjectFactoryBean">
        <property name="jndiName" value="jdbc/nonXA" />
    </bean>

    <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource"     ref="nonXA" />
        <property name="configLocation" value="classpath:/hibernate.cfg.nonXA.xml" />
        <property name="entityInterceptor">
            <bean class="sero.chase.integration.Hibernate.DB2Interceptor"/>
        </property>
    </bean>

    <bean id="session.XA.Factory"
        class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
        <property name="dataSource"     ref="XA" />
        <property name="configLocation" value="classpath:/hibernate.cfg.XA.xml" />
        <property name="entityInterceptor">
            <bean class="sero.chase.integration.Hibernate.DB2Interceptor"/>
        </property>
    </bean>

    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <bean id="transaction.XA.Manager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="session.XA.Factory" />
    </bean>

    <bean id="transactionAttributeSource"
        class="org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource">
        <property name="properties">
            <props>
                <prop key="*">PROPAGATION_REQUIRED</prop>
            </props>
        </property>
    </bean>

    <!-- App Bean Definitions (Two dao configurations excluding several other bean configurations are displayed below) -->

    <bean id="exampleDao"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
        lazy-init="true">
        <property name="transactionManager"         ref="transactionManager" />
        <property name="transactionAttributeSource" ref="transactionAttributeSource" />
        <property name="target">
            <bean class="sero.chase.integration.PersistenceImpl.ExamplePersistenceImpl">
                <property name="sessionFactory"     ref="sessionFactory" />
            </bean>
        </property>
    </bean>

     <bean id="exampleXADao"
        class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean"
        lazy-init="true">
        <property name="transactionManager"         ref="transaction.XA.Manager" />
        <property name="transactionAttributeSource" ref="transactionAttributeSource" />
        <property name="target">
            <bean class="sero.chase.integration.PersistenceImpl.ExamplePersistenceImpl">
                <property name="sessionFactory"     ref="session.XA.Factory" />
            </bean>
        </property>
    </bean>

</beans>

Hibernate Non XA配置:

<hibernate-configuration>

        <session-factory>

             <property name="hibernate.dialect">
                sero.chase.integration.Hibernate.DB2390Dialect
            </property>

            <property name="hibernate.default_schema">SCHM</property>
            <property name="query.substitutions">yes 'Y', no 'N'</property>
            <property name="jdbc.use_streams_for_binary">true</property>
            <property name="show_sql">true</property>
            <property name="format_sql">true</property>
            <property name="transaction.factory_class">org.hibernate.transaction.JTATransactionFactory</property>
            <property name="jta.UserTransaction">java:comp/UserTransaction</property>

            <property name="hibernate.cache.provider_class">
                org.hibernate.cache.EhCacheProvider
            </property>

            <!--===============-->
            <!-- mapping files -->
            <!--===============-->

            <mapping resource="sero/chase/integration/hbm/Example.hbm.xml" />

        </session-factory>

    </hibernate-configuration>

Hibernate XA配置:

<hibernate-configuration>

        <session-factory>

            <property name="hibernate.dialect">
                sero.chase.integration.Hibernate.DB2390Dialect
            </property>

            <property name="hibernate.default_schema">SCHMA</property>
            <property name="query.substitutions">yes 'Y', no 'N'</property>
            <property name="jdbc.use_streams_for_binary">true</property>
            <property name="show_sql">true</property>
            <property name="format_sql">true</property>
            <property name="hibernate.transaction.factory_class">org.hibernate.transaction.CMTTransactionFactory </property>
            <property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.WebSphereExtendedJTATransactionLookup</property>

            <property name="hibernate.cache.provider_class">
                org.hibernate.cache.EhCacheProvider
            </property>

            <!--===============-->
            <!-- mapping files -->
            <!--===============-->

            <mapping resource="sero/chase/integration/hbm/Example.hbm.xml" />

        </session-factory>

    </hibernate-configuration>

我的服务实现类的代码片段,其中发生了大多数业务逻辑:

public void someDeadlockCausingServiceMethod() {
    //The read1() method below is going to executing a select hql statement on Table A once the call goes all the way down to the Dao layer.
    List<SomeBeanInBusinessLayer> beanList = exampleBO.read1();

    //Do some processing with the values obtained from the read1() method
    ...
    //

    //saveOrUpdate() method below is going to execute an update hql statement on Table A once the call goes all the way down to the Dao layer 
    //where the values from someBeanInBusinessLayer is going to be copied into someBeanInDaoLayer before saving.
    exampleBO.saveOrUpdate(someBeanInBusinessLayer)

    //The read2() method below is going to execute a select hql statement that contains two inner selects (on Table B, C and D) once the call goes all
    //the way down to the Dao layer.
    List<SomeBeanInBusinessLayer2> beanList2 = exampleBO.read2();

    //Do some processing with the values obtained from the read2() method inside a for loop
    for(SomeBeanInBusinessLayer2 s: beanList2) {

        //Read values from table E
        List<SomeBeanInBusinessLayer3> beanList3 = exampleBO.read3(s.getProp2());

        SomeBeanInBusinessLayer2 someBeanInBusinessLayer2 = new SomeBeanInBusinessLayer2();
        someBeanInBusinessLayer2.setProp1(s.getProp2());
        someBeanInBusinessLayer2.setProp1(someBeanInBusinessLayer3.getProp2());
        //... more processing...
        //Below method will execute an insert hql on Table F
        exampleBO.saveOrUpdate(someBeanInBusinessLayer2);

        SomeBeanInBusinessLayer3 someBeanInBusinessLayer3 = new SomeBeanInBusinessLayer3();
        someBeanInBusinessLayer3.setProp1(s.getProp5());
        //... more processing...
        //Below method will execute an insert hql on Table G
        exampleBO.saveOrUpdate(someBeanInBusinessLayer3);
    }
}

public void anotherDeadlockCausingServiceMethod() {
    //The read1() method below is going to executing a select hql statement on Table A once the call goes all the way down to the Dao layer.
    List<SomeBeanInBusinessLayer> beanList = exampleBO.read1();

    //The read2() method below is going to executing a select hql statement on Table F once the call goes all the way down to the Dao layer.
    List<SomeBeanInBusinessLayer2> beanList2 = exampleBO.read2();

    //The read1() method below is going to executing a select hql statement on Table G once the call goes all the way down to the Dao layer.
    List<SomeBeanInBusinessLayer3> beanList3 = exampleBO.read3();

    //Do some processing with the values obtained...

    //Do an update on Table A
    exampleBO.saveOrUpdate(someBeanInBusinessLayer1)

    //Do an update on Table F
    exampleBO.saveOrUpdate(someBeanInBusinessLayer2)
}

我的Dao layer1中的代码段:

public void load(BeanDTO beanDTO) {
    Object param1 = beanDTO.getBeanList().getProp1();
    Object param2 = beanDTO.getBeanList().getProp2();
    List<SomeBeanInDaoLayer> beanList = null;
    Object[] params = {param1, param2};
          UserTransaction ut = null;
    try {
      Context context = new InitialContext();
      ut = (UserTransaction) context.lookup(Constant.USR_TRANSACTION);
      ut.begin();   
            beanList = beanDao2.load(params);
            ut.commit();
    }
    catch(Exception e) {
                    try {
                         ut.rollback();
                    }
                    catch(Exception e1) {
                    if(logger.isDebugEnabled()) {
           logger.debug("DB Exception", e1);
        }
                    }
        int error = ExceptionResolver.resolve(e);
        if(logger.isDebugEnabled()) {
            logger.debug("DB Exception", e);
        }
        beanDTO.setErrorCode(error);
    }
    beanDTO.setBeanList(beanList);
}

public void save(BeanDTO beanDTO) {
    List<SomeBeanInDaoLayer> beanList = beanDTO.getBeanList();
    for(SomeBeanInDaoLayer bean: beanList) {
        try {
                      Context context = new InitialContext();
                ut = (UserTransaction) context.lookup(Constant.USR_TRANSACTION);
                ut.begin(); 
                      beanDao2.save(bean);
                      ut.commit();
        }
        catch(Exception e) {
                       try {
                         ut.rollback();
                       }
                       catch(Exception e1) {
                         if(logger.isDebugEnabled()) {
               logger.debug("DB Exception", e1);
             }
                       }
            int err = ExceptionResolver.resolve(e);
            if(logger.isInfoEnabled()) {
                logger.info("DB Exception", e);
            }
            beanDTO.setErrorCode(err);
        }
    }
}

我的Dao Layer2中的代码窃听器:

public List<Bean> load(Object[] params) {
    String hql = "from Bean where beanProp1 = ? and beanProp2 = ?";
    return (List<Bean>) getHibernateTemplate().find(hql, params);
}

public void save(Bean bean) {
    getHibernateTemplate().saveOrUpdate(bean);
}
  1. 该应用程序是一个测试系统,用户可以在其中同时进行测试。
  2. 最初,事务划分不是在我的Dao层上,而是在我的服务实现类(实际上一直在我的控制器类上)说的,其中在一次开始提交块中将多次读取和更新绑定到一个事务中。由于我看到了多个死锁,因此将分界线移到了Dao层,以便在begin-commit块之间只有一个hql语句,以查看它是否防止了死锁,但是没有运气。
  3. 尝试将诸如hibernate.connection.autocommit设置为true,将hibernate.transaction.flush_before_completion设置为true并将hibehibernate.transaction.auto_close_session设置为true的属性没有成功。
  4. 从来没有一个用户读取的行被另一用户更新。即使每个用户访问相同的DB2表,它们也会读取和更新不同的行。仅在运行为测试构建一组问题的过程时,两个用户如果进行相同类型的测试,便会读取相同的行。它与上述someDeadlockCausingMethod非常相似,其中测试问题是从一组包含问题和答案的表中准备的。通过遍历for循环内的此结果集,将新行插入到另一个表中,以保存将出现在用户测试中的每个问题的详细信息。该步骤在应用程序中是必需的,因为即使两个用户参加相同的测试,也会从每个用户的所有问题池中抽取一组随机问题。
  5. 现在已经为参加考试的用户准备了考试,应用程序中的下一个逻辑步骤是从表中读取行,这些行仅包含与参加考试的用户有关的问题的详细信息。因此,并发用户将在此过程中读取同一表,但永远不会读取同一行。一次向用户显示一个问题。一旦用户回答了问题,将使用答案选项更新读取的行以获取与该用户有关的问题。再一次,永远不会为两个并发用户更新相同的行。此方法类似于上述的anotherDeadlockCausingMethod()。
  6. 希望您对应用程序的功能有所了解。并发用户从未读取或更新相同的行这一事实使我对如何锁定资源感到惊讶。然后,我发现对表进行更新时已进行了页面锁定。所以我去问DBA,他是否可以将其更改为正在更新的表上的行锁定。他担心实现行锁的DB2的性能开销,并担心它是否会影响使用DB2的其他应用程序。因此,除非我找不到其他解决方案,否则他不想这样做。
  7. 请忘记XA / JMS部分。假设该部分暂时被注释掉了。对于应用程序的大部分内容,我会在看到死锁的地方使用非XA数据源。

有人可以告诉我如何解决僵局吗?我想了解设计中出了什么问题。任何帮助都非常感谢


问题答案:

最终,我执行了干净的运行而没有死锁,它执行以下操作:

  1. hibernate.connection.isolation = 2
  2. 在我的select语句的末尾添加了“用cs更新”。
  3. 我正在使用saveOrUpdate()hibernate方法进行更新和插入。现在我改为使用save()进行插入,并使用update()进行更新。

我不明白的一件事是,为什么与我现在使用的“ with cs”相比,在我的select语句末尾使用“ with ur”不能解决死锁。想知道数据库的隔离级别,“
rs”需要做什么呢?