Estamos experimentando un error Oracle Deadlock (org.hibernate.util.JDBCExceptionReporter - ORA-00060: interbloqueo detectado mientras se espera el recurso). Se ha sugerido que el problema está en un proceso que está realizando operaciones de solo lectura usando Hibernate mientras que otro proceso está realizando una actualización en la misma fila.Oracle Deadlock cuando la aplicación Hibernate carga datos para uso de solo lectura
El proceso de solo lectura en cuestión se configura con Hibernate y Spring. No hemos definido explícitamente una transacción para el servicio. Si bien eso puede no ser el ideal, no veo por qué Hibernate intentaría obtener un bloqueo exclusivo en una fila cuando no se realizaban operaciones de guardado/actualización, solo un get/load.
Así que mi pregunta es: ¿Hibernate, cuando no se define una gestión explícita de transacciones, intenta obtener un bloqueo de lectura/escritura en una fila incluso si solo se realiza una "carga" de un objeto. No se realiza ninguna operación de guardar/actualizar.
¿Es posible que definir una transacción alrededor del servicio que está cargando datos y decir específicamente READONLY en transactionAttributes haga que Hibernate ignore un bloqueo de fila ya existente y simplemente cargue los datos con fines de solo lectura?
Éstos son algunos ejemplos de código:
para cargar el registro estamos utilizando un HibernateDaoTemplate
public class HibernatePurchaseOrderDataService extends HibernateDaoSupport implements PurchaseOrderDataService {
public PurchaseOrderData retrieveById(Long id) {
return (PurchaseOrderData)getHibernateTemplate().get(PurchaseOrderData.class, id);
}
}
La configuración de la primavera para el servicio de llamar a este método es:
<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>
El actual se produce un interbloqueo en uno de los registros PurchaseOrderItem cargados por la llamada a la carga de PurchaseOrder.
¿Causaría esto un punto muerto si el registro cargado estuviera bloqueado por otro proceso? Y en caso afirmativo, ¿sería útil resolver el problema al agregar un contenedor de transacciones como el que se muestra a continuación?
<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>
Actualización: El equipo de base de datos ha visto los mensajes de rastreo en el servidor que parecen indicar que nuestro proceso de "sólo lectura" es en realidad escribiendo a la base de datos de forma automática. Hay comandos registrados de "ACTUALIZACIÓN" que se realizan en las columnas exactas que estamos leyendo de la base de datos. Parece que Hibernate está escribiendo automáticamente estos registros en la base de datos (aunque no lo solicitemos). Eso probablemente explicaría por qué hay un punto muerto.
¿Podría ser por una Sesión FLUSH o algo similar? Pareciendo más como la solución podría ser usar un envoltorio de transacción con readOnly en él ...
Esto no es exactamente lo que estaba sucediendo, pero parecía similar. Los valores no se estaban "configurando" en el código. De hecho, Hibernate intentaba volver a escribir los mismos datos por algún motivo (los datos en el DB nunca se actualizaban con valores diferentes). – jonathanq