应用程序日志中的异常:
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>
休眠非 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>
休眠 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);
}
- 该应用程序是一个测试系统,用户可以同时进行测试。
- 最初,事务分界不在我的 Dao 层,而是在我的服务实现类(实际上一直在我的控制器类),其中多个读取和更新被绑定到开始提交块中的一个事务中。由于我看到了几个死锁,所以我将分界线移到了 Dao 层,以便在我的 begin-commit 块之间只有一个 hql 语句,以查看它是否可以防止死锁但没有运气。
- 尝试将 hibernate.connection.autocommit 等属性设置为 true,将 hibernate.transaction.flush_before_completion 设置为 true,将 hibehibernate.transaction.auto_close_session 设置为 true,但没有成功。
- 一个用户读取的行永远不会被另一个用户更新。每个用户都读取和更新不同的行,即使他们访问相同的 DB2 表。只有在运行为测试构建一组问题的过程时,如果两个用户进行相同类型的测试,他们将读取相同的行。它与上面描述的 someDeadlockCausingMethod 非常相似,其中测试问题是从一组包含问题和答案的表中准备的。通过在 for 循环中遍历此结果集,将新行插入到另一个表中以保存将出现在用户测试中的每个问题的详细信息。此步骤在应用程序中是必要的,因为即使两个用户参加相同的测试,也会从每个用户的所有问题池中抽取一组随机问题。
- 现在测试已为参加考试的用户准备好,应用程序中的下一个逻辑步骤是从仅包含与参加考试的用户有关的问题的详细信息的表中读取行。因此,并发用户将在此过程中读取同一张表,但不会读取同一行。一次向用户呈现一个问题。用户回答问题后,为获取与该用户有关的问题而读取的行将使用答案选项进行更新。再一次,永远不会为两个并发用户更新相同的行。此方法类似于上面描述的 anotherDeadlockCausingMethod()。
- 我希望您对应用程序的功能有所了解。并发用户从不读取或更新相同的行这一事实让我对资源如何被锁定感到惊讶。然后我发现页面锁定是为了更新表格。所以我去问 DBA 是否可以将其更改为对正在更新的表进行行锁定。他担心 DB2 实现行锁定的性能开销,并担心它是否会影响使用 DB2 的其他应用程序。所以他不想这样做,除非我找不到任何其他解决方案。
- 请忘记 XA/JMS 部分。假设该部分暂时被注释掉。对于我看到死锁的大部分应用程序非 XA 数据源。
有人可以告诉我如何解决僵局吗?我想了解设计中出了什么问题。提前非常感谢任何帮助