Java 检测到死锁时休眠会话不同步

Java 检测到死锁时休眠会话不同步,java,hibernate,hibernate-mapping,database-deadlocks,Java,Hibernate,Hibernate Mapping,Database Deadlocks,我有以下场景来保存我的对象 // Started transaction User objUser = getUser("123");// get user from DB objUser.set(...) . . UserAddress objUserAddress = objUser.getUserAddress(); objUserAddress.set(..); . . hibernateSession.flush(); //#Line 1 hibernateSession.saveOr

我有以下场景来保存我的对象

// Started transaction
User objUser = getUser("123");// get user from DB
objUser.set(...)
.
.
UserAddress objUserAddress = objUser.getUserAddress();
objUserAddress.set(..);
.
.
hibernateSession.flush(); //#Line 1
hibernateSession.saveOrUpdate(objUserAddress); //#Line 2
hibernateSession.flush(); //#Line 3
hibernateSession.saveOrUpdate(objUser); //#Line 4
// Commit transaction
下面是用户和地址类之间的hibernate映射

<class name="com.service.core.bo.impl.User" table="USERS">
.
.
<many-to-one name="userAddress" class="com.service.core.bo.impl.UserAddress"
        column="ADDRESS_ID" not-null="false" unique="true" cascade="save-update"
        lazy="false" />
.
.
</class>
问题是,这个错误并不一致。这可能会在一天内发生一次或多次,而在另一天则不会发生。
不确定为什么
flush()
导致
无法将数据库状态与会话同步
ORA-00060:在等待资源时检测到死锁
。我找到了一些类似于会话状态的链接,但实际原因是死锁,如上述异常。

无法将数据库状态与会话同步。是一个常见的休眠错误,可能有多个根本原因。 您应该关注的错误是:

ORA-00060:等待资源时检测到死锁

这是特定于Oracle的,当从多个连接更新同一数据(数据库中的行)时会发生这种情况。每当Oracle(实际上是任何数据库)更新一行时,它都会在更新期间锁定该行。如果在锁定时在同一行上尝试另一次更新,则会发生此错误。 以下是Oracle的官方错误解释:

ORA-00060:等待资源时检测到死锁

原因:事务在等待资源时彼此死锁

操作:查看跟踪文件以查看所涉及的事务和资源。如有必要,请重试

解决此问题的一种方法是使用版本控制:


这将向表中添加一个版本列,该列在更新行时自动递增。在更新之前,会检查版本,如果版本高于预期版本,则更新后的版本甚至不会更新,并抛出一个特定错误,您可以处理该错误。通常,处理包括从数据库中重新加载该实体的信息,将其值重置为所需值,然后保存

无法将数据库状态与会话同步是一个常见的休眠错误,可能有多个根本原因。 您应该关注的错误是:

ORA-00060:等待资源时检测到死锁

这是特定于Oracle的,当从多个连接更新同一数据(数据库中的行)时会发生这种情况。每当Oracle(实际上是任何数据库)更新一行时,它都会在更新期间锁定该行。如果在锁定时在同一行上尝试另一次更新,则会发生此错误。 以下是Oracle的官方错误解释:

ORA-00060:等待资源时检测到死锁

原因:事务在等待资源时彼此死锁

操作:查看跟踪文件以查看所涉及的事务和资源。如有必要,请重试

解决此问题的一种方法是使用版本控制:


这将向表中添加一个版本列,该列在更新行时自动递增。在更新之前,会检查版本,如果版本高于预期版本,则更新后的版本甚至不会更新,并抛出一个特定错误,您可以处理该错误。通常,处理包括从数据库中重新加载该实体的信息,将其值重置为所需值,然后保存

感谢并对延迟回复表示歉意。两个资源试图同时更新时发生死锁是正确的。但是在我的例子中,我只在
flush()
方法上得到了这个异常。是的,这是正常的,因为只有这样,您所做的更改才真正应用到数据库。saveOrUpdate()将不执行数据库操作,在调用flush()时所有操作都已完成。感谢并为响应延迟表示歉意。两个资源试图同时更新时发生死锁是正确的。但是在我的例子中,我只在
flush()
方法上得到了这个异常。是的,这是正常的,因为只有这样,您所做的更改才真正应用到数据库。saveOrUpdate()不会执行数据库操作,所有操作都在调用flush()时完成。
[2017-12-12 11:15:02.131 GMT] WARN [] [] [] [] [] [] [] [] [] http-bio-8280-exec-14 org.hibernate.util.JDBCExceptionReporter - SQL Error: 60, SQLState: 61000
[2017-12-12 11:15:02.131 GMT] ERROR [] [] [] [] [] [] [] [] [] http-bio-8280-exec-14 org.hibernate.util.JDBCExceptionReporter - ORA-00060: deadlock detected while waiting for resource

[2017-12-12 11:15:02.131 GMT] ERROR [] [] [] [] [] [] [] [] [] http-bio-8280-exec-14 org.hibernate.event.def.AbstractFlushingEventListener - 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:172)
        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 sun.reflect.GeneratedMethodAccessor706.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
       .
       .
Caused by: java.sql.BatchUpdateException: ORA-00060: deadlock detected while waiting for resource
        at oracle.jdbc.driver.OraclePreparedStatement.executeBatch(OraclePreparedStatement.java:12296)
        at oracle.jdbc.driver.OracleStatementWrapper.executeBatch(OracleStatementWrapper.java:246)
        at sun.reflect.GeneratedMethodAccessor553.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:498)
        at oracle.ucp.jdbc.proxy.StatementProxyFactory.invoke(StatementProxyFactory.java:353)
        at oracle.ucp.jdbc.proxy.PreparedStatementProxyFactory.invoke(PreparedStatementProxyFactory.java:178)
        at com.sun.proxy.$Proxy66.executeBatch(Unknown Source)
        at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:48)
        at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:246)
        ... 71 more