Java 如何防止Oracle数据库+Hibernate中的死锁

Java 如何防止Oracle数据库+Hibernate中的死锁,java,oracle,hibernate,oracle10g,oracle-enterprise-manager,Java,Oracle,Hibernate,Oracle10g,Oracle Enterprise Manager,我正在使用oracle数据库和Java/Hibernate,如下表所示: Id| Status |.... 1 PENDING 2 COMPLETED 从两个不同的事务中,执行以下查询: 1)select particular record, then update it for(select some record from table){ update record status to COMPLETED session.flush() } 2) update records

我正在使用oracle数据库和Java/Hibernate,如下表所示:

Id| Status |....
1  PENDING
2  COMPLETED
从两个不同的事务中,执行以下查询:

1)select particular record, then update it
for(select some record from table){
  update record status to COMPLETED
  session.flush()
}
2) update records bunch
update table set status = 'PENDING' where....
查询可以按任何顺序执行,因此1可以出现在2之前,反之亦然

因此,我永远执行查询2,所以我认为这是死锁情况。Oracle Enterprise Manager显示查询2等待发送锁定

我如何处理这种情况


我读到关于选择。。。对于Hibernate中的update constructionlockmode.upgrade,但在这种情况下,我认为它将锁定整个表,因此执行时间将增加。

死锁与阻塞锁非常不同。您所描述的似乎是一个阻塞锁。你的for中有谓词吗?或者您是从表中选择每一行吗?您能否澄清这两个事务的时间安排?事务1的操作是否发生在第二个事务开始之前?当第二个开始时,第一个提交了更改吗?如果第二个事务在第一个提交之前在另一个连接上启动,它当然会锁定。如果没有公共行,则不会有阻塞。如果第一个事务正在更新与第二个事务完全不同的行集,那么第二个事务应该没有理由阻止。您是否绝对确定这两个会话没有尝试更新同一行?当第二个会话被阻止时,完整的v$lock输出是什么?否。即使第二个查询使用完全扫描来访问表,它也只会锁定正在更新的行。它不会锁定任何其他行。如果确实存在行锁争用,这似乎是问题所暗示的,但是v$lock表可能会讲述一个稍微不同的故事,那么这两个查询必须尝试更新同一行。执行select for update可能会有所帮助。另一方面,它可能会将阻塞锁问题变成实际的死锁问题。或者它可能会改变这两个进程中的哪一个阻塞。如果您不希望用两个进程更新同一行,那么找出为什么有两个进程试图将同一行更新为不同的值似乎比更改锁定方案更有成效。