gpt4 book ai didi

当 Hibernate 应用程序加载数据以供只读使用时 Oracle 死锁

转载 作者:行者123 更新时间:2023-12-04 21:01:03 25 4
gpt4 key购买 nike

我们遇到了 Oracle 死锁(org.hibernate.util.JDBCExceptionReporter - ORA-00060:在等待资源时检测到死锁)错误。有人建议问题出在使用 Hibernate 执行只读操作的进程,而另一个进程正在对同一行执行更新。

有问题的只读进程是使用 Hibernate 和 Spring 配置的。我们没有为服务明确定义事务。虽然这可能并不理想 - 我不明白为什么 Hibernate 会在没有执行保存/更新操作的情况下尝试获取行上的排他锁 - 只有获取/加载。

所以我的问题是:当没有定义显式事务管理时,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 配置为:
<bean id="orderDataService"
class="com.example.orderdata.HibernatePurchaseOrderDataService">
<property name="sessionFactory" ref="orderDataSessionFactory"/>
</bean>

<bean id="orderDataSessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="hibernateDataSource"/>
<property name="hibernateProperties" ref="hibernateProperties"/>
<property name="mappingResources">
<list>
<value>com/example/orderdata/PurchaseOrderData.hbm.xml</value>
<value>com/example/orderdata/PurchaseOrderItem.hbm.xml</value>
</list>
</property>
</bean>

实际死锁发生在通过调用加载 PurchaseOrder 加载的 PurchaseOrderItem 记录之一上。

如果正在加载的记录被另一个进程锁定,这会导致死锁吗?如果是这样 - 添加一个如下所示的交易包装器会解决问题吗?
<bean id="txWrappedOrderDataService"
class="org.springframework.transaction.interceptor.TransactionProxyFactoryBean">
<property name="transactionManager" ref="transactionManager"/>
<property name="target" ref="orderDataService"/>
<property name="transactionAttributes">
<props>
<!-- all methods require a transaction -->
<prop key="*">PROPAGATION_REQUIRED,readOnly</prop>
</props>
</property>
</bean>

更新:DataBase 团队在服务器上看到了跟踪消息,这些消息似乎表明我们的“只读”进程实际上正在自动写入数据库。记录了对我们从数据库中读取的确切列执行的“UPDATE”命令。似乎 Hibernate 会自动将这些记录写回数据库(即使我们没有要求它)。这可能可以解释为什么会出现僵局。

这可能是因为 session FLUSH 或类似的原因吗?看起来更像是解决方案可能是使用带有只读的事务包装器......

最佳答案

当您使用操作它们实际设置的值的 setter 时,hibernate 可能会发生非自愿更新。一个例子是 String 属性的 setter,它用 ""替换 null 值。一个可能的候选者也是集合。确保 setter 不会替换包含的集合。如果你用另一个包含相同内容的集合替换一个实体的集合,hibernate 将无法意识到这一点并更新完整的集合。

关于当 Hibernate 应用程序加载数据以供只读使用时 Oracle 死锁,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/663250/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com