Wir haben einen Oracle-Deadlock-Fehler (org.hibernate.util.JDBCExceptionReporter - ORA-00060: Deadlock beim Warten auf Ressource festgestellt) festgestellt. Es wurde vorgeschlagen, dass das Problem bei einem Prozess auftritt, der schreibgeschützte Operationen mit Hibernate durchführt, während ein anderer Prozess eine Aktualisierung für dieselbe Zeile ausführt.Oracle Deadlock, wenn die Hibernate-Anwendung Daten für die schreibgeschützte Verwendung lädt
Der fragliche schreibgeschützte Prozess wird mit Hibernate und Spring konfiguriert. Wir haben keine Transaktion für den Service explizit definiert. Auch wenn das nicht ideal ist - ich verstehe nicht, warum Hibernate versuchen würde, eine exklusive Sperre für eine Zeile zu erhalten, wenn keine Speicher-/Aktualisierungsoperationen ausgeführt wurden - nur ein get/load.
Also meine Frage ist: Ist Hibernate, wenn keine explizite Transaktionsverwaltung definiert ist, versuchen Sie, eine Lese-/Schreibsperre für eine Zeile zu erhalten, auch wenn nur ein "Laden" eines Objekts ausgeführt wird. Kein Speichern/Aktualisieren wird durchgeführt.
Ist es möglich, dass das Definieren einer Transaktion um den Dienst, der Daten lädt, und READONLY spezifisch auf den transactionAttributes sagt, Hibernate eine bereits vorhandene Zeilensperre ignoriert und nur die Daten für schreibgeschützte Zwecke lädt?
Hier sind einige Code-Beispiele:
Für das Laden der Platte, die wir eine HibernateDaoTemplate verwenden
public class HibernatePurchaseOrderDataService extends HibernateDaoSupport implements PurchaseOrderDataService {
public PurchaseOrderData retrieveById(Long id) {
return (PurchaseOrderData)getHibernateTemplate().get(PurchaseOrderData.class, id);
}
}
Die Spring-Konfiguration für den Dienst Aufruf dieser Methode ist:
<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>
die tatsächliche Deadlock tritt bei einem der PurchaseOrderItem-Datensätze auf, die durch den Aufruf des PurchaseOrder geladen werden.
Würde dies zu einem Deadlock führen, wenn der geladene Datensatz von einem anderen Prozess gesperrt wurde? Und wenn ja - würde das Hinzufügen eines Transaktions-Wrappers wie dem folgenden das Problem lösen?
<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: Das Datenbank-Team hat auf dem Server Trace-Nachrichten zu sehen, die darauf hindeuten, dass unser „Nur-Lesen“ Prozess tatsächlich wird automatisch in die Datenbank zu schreiben. Es gibt protokollierte "UPDATE" -Befehle, die für die exakten Spalten ausgeführt werden, die wir aus der Datenbank lesen. Es scheint, dass Hibernate diese Datensätze automatisch wieder in die Datenbank schreibt (obwohl wir das nicht verlangen). Das würde wahrscheinlich erklären, warum es einen Stillstand gibt.
Könnte dies wegen einer Session FLUSH oder etwas ähnliches sein? Sieht eher aus wie die Lösung, einen Transaktions-Wrapper mit readOnly zu verwenden ...
Dies ist nicht genau das, was geschah - aber schien ähnlich. Die Werte wurden nicht im Code "gesetzt". Hibernate versuchte tatsächlich, die gleichen Daten aus irgendeinem Grund zurückzuschreiben (die Daten in der Datenbank wurden nie auf andere Werte aktualisiert). – jonathanq