数据库死锁问题
最近遇到一个问题:在两个线程执行同一段保存的操作时,报数据库死锁问题。以下是代码:
// 这是某Service的一个方法
public void test(){
......
hemsMMatchTaskDao.save(hemsMMatchTask);
hemsMMatchTaskDao.flush();// 这里报错了
}
大牛们帮忙分析分析,根本原因应该是什么?
我想在代码那加一个同步锁:
public void test(){
......
synchronized (TestServiceImpl.class) {
hemsMMatchTaskDao.save(hemsMMatchTask);
hemsMMatchTaskDao.flush();// 这里报错了
}
hemsMMatchTaskDao.save(hemsMMatchTask);
hemsMMatchTaskDao.flush();// 这里报错了
}
不知道这种方法是否可行。。。
--------------------编程问答-------------------- 以下是报错信息:
2013-12-05 04:10:16 [org.hibernate.util.JDBCExceptionReporter.logExceptions(JDBCExceptionReporter.java:77)]-[WARN] SQL Error: 60, SQLState: 61000
2013-12-05 04:10:16 [org.hibernate.util.JDBCExceptionReporter.logExceptions(JDBCExceptionReporter.java:78)]-[ERROR] ORA-00060: deadlock detected while waiting for resource
2013-12-05 04:10:16 [org.hibernate.util.JDBCExceptionReporter.logExceptions(JDBCExceptionReporter.java:77)]-[WARN] SQL Error: 60, SQLState: 61000
2013-12-05 04:10:16 [org.hibernate.util.JDBCExceptionReporter.logExceptions(JDBCExceptionReporter.java:78)]-[ERROR] ORA-00060: deadlock detected while waiting for resource
2013-12-05 04:10:16 [org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:301)]-[ERROR] Could not synchronize database state with session
org.hibernate.exception.LockAcquisitionException: Could not execute JDBC batch update
at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:87)
at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:253)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:168)
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.springframework.orm.hibernate3.HibernateTemplate$27.doInHibernate(HibernateTemplate.java:818)
at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:373)
at org.springframework.orm.hibernate3.HibernateTemplate.flush(HibernateTemplate.java:816)
at com.zjhcsoft.common.persistence.hibernate.BaseDaoHibernateImpl.flush(BaseDaoHibernateImpl.java:371)
at com.zjhcsoft.hems.packagemanage.service.impl.HemsMMatchTaskServiceImpl.saveAutoMatchTask(HemsMMatchTaskServiceImpl.java:287)
at sun.reflect.GeneratedMethodAccessor3123.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:301)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy121.saveAutoMatchTask(Unknown Source)
at com.zjhcsoft.hems.autoflow.service.impl.HemsAutoflowExecuteActivityMatchServiceImpl.manualMatch(HemsAutoflowExecuteActivityMatchServiceImpl.java:360)
at com.zjhcsoft.hems.autoflow.service.impl.HemsAutoflowExecuteActivityMatchServiceImpl.saveTaskHandle(HemsAutoflowExecuteActivityMatchServiceImpl.java:217)
at sun.reflect.GeneratedMethodAccessor2708.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:301)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:89)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at $Proxy124.saveTaskHandle(Unknown Source)
at com.zjhcsoft.hems.autoflow.HemsSpringHelper.taskHandleMatchService(HemsSpringHelper.java:53)
at com.zjhcsoft.hems.autoflow.jbpm4activity.HemsAutoflowMatchActivity.execute(HemsAutoflowMatchActivity.java:21)
at org.jbpm.pvm.internal.wire.usercode.UserCodeActivityBehaviour.execute(UserCodeActivityBehaviour.java:42)
at org.jbpm.pvm.internal.model.op.ExecuteActivity.perform(ExecuteActivity.java:60)
at org.jbpm.pvm.internal.model.ExecutionImpl.performAtomicOperationSync(ExecutionImpl.java:672)
at org.jbpm.pvm.internal.model.ExecutionImpl.performAtomicOperation(ExecutionImpl.java:632)
at org.jbpm.pvm.internal.model.ExecutionImpl.signal(ExecutionImpl.java:430)
at org.jbpm.pvm.internal.cmd.SignalCmd.execute(SignalCmd.java:61)
at org.jbpm.pvm.internal.cmd.SignalCmd.execute(SignalCmd.java:35)
at org.jbpm.pvm.internal.svc.DefaultCommandService.execute(DefaultCommandService.java:42)
at org.jbpm.pvm.internal.tx.SpringCommandCallback.doInTransaction(SpringCommandCallback.java:45)
at org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:128)
at org.jbpm.pvm.internal.tx.SpringTransactionInterceptor.execute(SpringTransactionInterceptor.java:49)
at org.jbpm.pvm.internal.svc.EnvironmentInterceptor.executeInNewEnvironment(EnvironmentInterceptor.java:53)
at org.jbpm.pvm.internal.svc.EnvironmentInterceptor.execute(EnvironmentInterceptor.java:40)
at org.jbpm.pvm.internal.svc.RetryInterceptor.execute(RetryInterceptor.java:56)
at org.jbpm.pvm.internal.svc.ExecutionServiceImpl.signalExecutionById(ExecutionServiceImpl.java:89)
at com.zjhcsoft.hems.autoflow.jbpm4activity.Jbpm4InstanceSignalThread.run(Jbpm4InstanceSignalThread.java:21)
Caused by: java.sql.BatchUpdateException: ORA-00060: deadlock detected while waiting for resource
at oracle.jdbc.driver.DatabaseError.throwBatchUpdateException(DatabaseError.java:342)
at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:10720)
at com.mchange.v2.c3p0.impl.NewProxyPreparedStatement.executeBatch(NewProxyPreparedStatement.java:1723)
at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246)
... 58 more --------------------编程问答-------------------- 大牛们帮忙分析分析,根本原因应该是什么?
我想在代码那加一个同步锁:
public void test(){
......
synchronized (TestServiceImpl.class) {
hemsMMatchTaskDao.save(hemsMMatchTask);
hemsMMatchTaskDao.flush();// 这里报错了
}
}
不知道这种方法是否可行。。。 --------------------编程问答-------------------- 是不是2个线程更新的同一条数据哦。
你可以更新的时候做个判断。比如更新时间,这次的更新时间和上次的不一样就不要更新。 --------------------编程问答--------------------
保存的是不一样的数据。前一条执行的数据保存成功了,后面一条就报错了 --------------------编程问答-------------------- 保存的时候为何要加同步呢 保存数据又不冲突 --------------------编程问答-------------------- 加同步肯定可以解决问题。如果性能可以接受的话。
我觉得可以看看 hemsMMatchTaskDao 是不是一个定义好的 Entity, 然后update这个有没有一些关联的表或者数据库里面的trigger,可能会有冲突 --------------------编程问答-------------------- 还有,把hibernate的showsql打开看看,具体的sql语句 --------------------编程问答--------------------
保存的实体()的序列号不是保存的时候自动生成的,而是先获取id,再set给实体,再保存实体。这样的机制是不是造成保存出错的原因??? --------------------编程问答-------------------- 应该是行锁了。
补充:Java , Java EE