Oracleデッドロック(org.hibernate.util.JDBCExceptionReporter - ORA-00060:リソースの待機中にデッドロックが検出されました)エラーが発生しました。この問題は、別のプロセスが同じ行の更新を実行している間にHibernateを使用して読み取り専用操作を実行しているプロセスであることが示唆されています。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レコードの1つで発生しています。
ロードされているレコードが別のプロセスによってロックされていた場合、デッドロックが発生しますか?もしそうなら、以下のようなトランザクションラッパーを追加すると問題が解決されますか?
<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>
更新:データベースチームは、当社の「読み取り専用」のプロセスが実際に自動的にデータベースに書き込んでいることを示しているように見えるのサーバー上でトレースメッセージを見ています。ログに記録されている「UPDATE」コマンドは、データベースから読み取っている正確な列に対して実行されます。 Hibernateはこれらのレコードをデータベースに自動的に書き出しているように思われます(たとえそれを要求していなくても)。それはたぶんデッドロックがある理由を説明するでしょう。
セッションFLUSHなどの理由が考えられますか?ソリューションのようにもっと見ると、readOnlyを使ってトランザクションラッパーを使用することができます...
これは正確に起こったことではありませんが、類似しているようです。値はコード内で「設定」されていませんでした。 Hibernateは何らかの理由で同じデータを実際に書き戻そうとしていました(DB内のデータは決して異なる値に更新されませんでした)。 – jonathanq