3

我開發了一個使用Spring-3.0 Hibernate-3.6.5和SpringHibernateTemplate作爲DAO的監視應用程序。數據庫SQL Server 2008.這個應用程序每天都有長時間運行的事務。調度程序在Spring事務中發生死鎖時停止

@Repository("areaDaoHibernate") 
public class AreaDAO implements IArea { 
     protected HibernateTemplate template = null; 

     @Autowired @Required 
     public void setSessionFactory(SessionFactory sessionFactory) { 
       template = new HibernateTemplate(sessionFactory); 
     } 

     // basic dao method 
} 

這個應用程序有一些調度(實現可運行)通過springbeans。

@Component("dailyTask") 
@Scope("prototype") 
public class DailyTask implements Runnable { 

@Override 
     public void run() { 
       // running task 
     } 
} 

此應用程序使用Apache DBCP進行池化。

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> 
       <property name="dataSource"> 
        <ref bean="CustodyDataSource" /> 
       </property> 
… 
     </bean> 

<bean id = "CustodyDataSource" 
     class    = "org.apache.commons.dbcp.BasicDataSource" 
     p:driverClassName = "${jdbc1.driverClassName}" 
     p:url    = "${jdbc1.url}" 
     p:username  = "${jdbc1.username}" 
     p:password  = "${jdbc1.password}" 
     p:maxIdle   = "${jdbc1.maxIdle}" 
     p:maxActive  = "${jdbc1.maxActive}" 
     p:validationQuery = "${jdbc1.validationQuery}" 
     p:testWhileIdle = "${jdbc1.testWhileIdle}" /> 
<bean id = "transactionManager" 
     class = "org.springframework.orm.hibernate3.HibernateTransactionManager" 
     p:sessionFactory-ref = "sessionFactory" /> 

我有問題,當這個應用程序死鎖,調度停止運行。
錯誤顯示:

2012-12-27 12:57:20,861 WARN (JDBCExceptionReporter:233) - SQL Error: 1205, SQLState: 40001 
2012-12-27 12:57:20,862 ERROR (JDBCExceptionReporter:234) - Transaction (Process ID 55) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction. 
2012-12-27 12:57:20,866 ERROR (DailyTask:238) - org.springframework.dao.CannotAcquireLockException: could not update: [com.btpn.custody.entity.MasterData#00176ed4-b7a2-4da5-a266-ffaab3654050]; SQL [update T_CIF set __UPDATED_DATE=?, STATUS_MD=? where __SID=?]; nested exception is org.hibernate.exception.LockAcquisitionException: could not update: [com.btpn.custody.entity.MasterData#00176ed4-b7a2-4da5-a266-ffaab3654050] 
      at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:633) 
      at org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:793) 
      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 $Proxy33.relateWithBranch(Unknown Source) 
      at com.btpn.custody.bean.DailyTask.relateMasterDataWithBranch(DailyTask.java:1166) 
      at com.btpn.custody.bean.DailyTask.manualInitial(DailyTask.java:213) 
      at com.btpn.custody.bean.DailyTask.run(DailyTask.java:197) 
      at java.lang.Thread.run(Unknown Source) 
Caused by: org.hibernate.exception.LockAcquisitionException: could not update: [com.btpn.custody.entity.MasterData#00176ed4-b7a2-4da5-a266-ffaab3654050] 
      at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:107) 
      at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66) 
      at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2612) 
      at org.hibernate.persister.entity.AbstractEntityPersister.updateOrInsert(AbstractEntityPersister.java:2494) 
      at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2821) 
      at org.hibernate.action.EntityUpdateAction.execute(EntityUpdateAction.java:113) 
      at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273) 
      at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265) 
      at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:185) 
      at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321) 
      at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51) 
      at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216) 
      at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383) 
      at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133) 
      at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656) 
      ... 11 more 
Caused by: java.sql.SQLException: Transaction (Process ID 55) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction. 
      at net.sourceforge.jtds.jdbc.SQLDiagnostic.addDiagnostic(SQLDiagnostic.java:368) 
      at net.sourceforge.jtds.jdbc.TdsCore.tdsErrorToken(TdsCore.java:2820) 
      at net.sourceforge.jtds.jdbc.TdsCore.nextToken(TdsCore.java:2258) 
      at net.sourceforge.jtds.jdbc.TdsCore.getMoreResults(TdsCore.java:632) 
      at net.sourceforge.jtds.jdbc.JtdsStatement.processResults(JtdsStatement.java:584) 
      at net.sourceforge.jtds.jdbc.JtdsStatement.executeSQL(JtdsStatement.java:546) 
      at net.sourceforge.jtds.jdbc.JtdsPreparedStatement.executeUpdate(JtdsPreparedStatement.java:504) 
      at org.apache.commons.dbcp.DelegatingPreparedStatement.executeUpdate(DelegatingPreparedStatement.java:102) 
      at org.hibernate.jdbc.NonBatchingBatcher.addToBatch(NonBatchingBatcher.java:46) 
      at org.hibernate.persister.entity.AbstractEntityPersister.update(AbstractEntityPersister.java:2590) 
      ... 23 more 

所以我的問題:

  1. 我應該改變連接池,以避免死鎖問題?
  2. 爲什麼我的調度bean在死鎖發生後停止運行?
+1

關於更改連接池:這不會改變任何東西(除非你想*不使用事務)。您需要修復您的應用程序以避免死鎖。可能你可以在SQL Server日誌中看到哪些行/表/資源是死鎖的一部分。 – Augusto

回答

1

死鎖發生在SQL Server中。這不是Spring,Hibernate,連接池和SQL Server錯誤。問題在於您的應用程序正在鎖定您的應用程序或其他應用程序也試圖鎖定的行(採用deadlock的方式)。

最簡單的修復方法可能是爲您的工作制定重試策略(如果失敗,只需重試整個事務)。通過查看SQL Server日誌,您還可以嘗試找出究竟哪些應用程序/用戶參與了死鎖。

+0

謝謝你的解釋,我現在可以專注於代碼 –