我们遇到Oracle死锁(org.hibernate.util.JDBCExceptionReporter - ORA-00060:在等待资源时检测到死锁)错误.有人建议问题在于使用Hibernate执行只读操作的进程,而另一个进程在同一行上执行更新.
有问题的只读进程是使用Hibernate和Spring配置的.我们没有明确定义服务的事务.虽然这可能不太理想 - 我不明白为什么Hibernate会在没有执行保存/更新操作时尝试在行上获得独占锁定 - 只有get/load.
所以我的问题是:当没有定义显式事务管理时,Hibernate是否尝试在一行上获得读/写锁,即使只执行了对象的"加载".不执行保存/更新.
是否有可能围绕正在加载数据的服务定义一个事务,然后在transactionAttributes上特别说READONLY会导致Hibernate忽略已经存在的行锁并只是加载数据以用于只读目的?
以下是一些代码示例:
为了加载记录,我们使用的是HibernateDaoTemplate
public class HibernatePurchaseOrderDataService extends HibernateDaoSupport implements PurchaseOrderDataService { public PurchaseOrderData retrieveById(Long id) { return (PurchaseOrderData)getHibernateTemplate().get(PurchaseOrderData.class, id); } }
调用此方法的服务的Spring配置是:
com/example/orderdata/PurchaseOrderData.hbm.xml com/example/orderdata/PurchaseOrderItem.hbm.xml
实际死锁发生在一个PurchaseOrderItem记录上,该记录是通过对LoadOrder的加载调用加载的.
如果正在加载的记录被另一个进程锁定,是否会导致死锁?如果是这样 - 添加一个事务包装器,如下面的那个解决问题?
PROPAGATION_REQUIRED,readOnly
更新:DataBase团队已在服务器上看到跟踪消息,这些消息似乎表明我们的"只读"进程实际上是自动写入数据库.记录的"UPDATE"命令是在我们从数据库中读取的确切列上执行的.似乎Hibernate会自动将这些记录写回数据库(即使我们没有要求它).这可能解释了为什么会出现僵局.
这可能是因为会话FLUSH或类似的东西?看起来更像解决方案可能是使用带有readOnly的事务包装器...