如何在休眠/弹簧中使用LOCK IN SHARE MODE?

时间:2011-01-05 11:11:44

标签: java mysql hibernate spring jpa

当使用MySQL和Hibernate(使用Spring)时,我遇到了死锁情况。我收到以下异常消息:

  

无法获取或更新下一个值;   SQL [空]。嵌套异常是   org.hibernate.exception.LockAcquisitionException   ...试图获得时发现死锁   锁;尝试重新启动交易

我的MySQL数据库的事务隔离级别配置为READ COMMITTED,我做了一些查看INNODB状态以查看发生死锁时发生的情况。基本上我看到两个事务,其中一个尝试从表中选择一行而另一个尝试更新该行。这里争论的表是我的“唯一ID”表。我有一个共同的根对象,其他@Entity对象扩展。此根对象定义“id”属性,并使用@ Id,@ TableGenerator和@GeneratedValue进行注释。

一些挖掘使我相信将LockMode设置为UPGRADE用于该表上的“选择”可能有助于和/或更改“选择”,以便使用“select .... for而不是更新“它会使用”选择.... 锁定共享模式“。

设置Lockmode.upgrade的任何想法都会真的有帮助或将“for update”更改为“锁定共享模式”?其次,我将如何使用spring + hibernate执行此操作...我倾向于实现自定义的LoadEventListener(它将扩展DefaultLoadEventListener)。

1 个答案:

答案 0 :(得分:0)

我遇到的特殊情况是死锁发生在我的“id generator”表中。最后我发现我的应用程序正在使用org.hibernate.id.MultipleHiLoPerTableGenerator来构建select语句(该类在内部将它存储在“query”属性中)并添加“for update”字符串(它实际上是从org.hibernate.dialect.Dialect类(getForUpdateString方法)。

此特定实例的解决方案是在我的Id表中执行“select”时,Id生成器使用“锁定共享模式”而不是“for update”。使用自定义方言(即覆盖getForUpdateString方法不可行b / c我不想一直'锁定共享模式',就在这种情况下)。

因此我必须创建自己的Id生成器类。我希望MultipleHiLoPerTableGenerator更容易扩展(即希望我可以覆盖'createSelectSql'方法)。