Las siguientes secciones describen algunos de los escenarios más comunes de punto muerto y algunas sugerencias para evitarlos.
Como resultado, se visualiza la siguiente excepción:
com.ibm.websphere.objectgrid.plugins.LockDeadlockException: Mensaje
Este mensaje representa la serie que se pasa como parámetro cuando se crea y se emite la excepción.Descripción: cuando una transacción o un cliente solicita que se otorgue un bloqueo para una entrada de correlación específica, la solicitud a menudo espera a que el cliente actual libere el bloqueo antes de enviar la solicitud. Si la solicitud de bloqueo permanece desocupada durante un periodo largo de tiempo, y no se otorga nunca un bloqueo, se crea una excepción LockTimeoutException para evitar un punto muerto, lo que se describe más detalladamente en la sección siguiente. Es más probable que vea esta excepción al utilizar una estrategia de bloqueo pesimista, ya que el bloqueo nunca se libera hasta que se confirma la transacción.
Recupere más detalles:
La excepción LockTimeoutException contiene el método getLockRequestQueueDetails, que devuelve una serie. Puede utilizar este método para ver una descripción detallada de la situación que desencadena la excepción. A continuación se muestra un ejemplo de código que detecta la excepción y visualiza un mensaje de error.
try {
...
}
catch (LockTimeoutException lte) {
System.out.println(lte.getLockRequestQueueDetails());
}
lock request queue
−>[TX:163C269E−0105−4000−E0D7−5B3B090A571D, state =
Granted 5348 milli−seconds ago, mode = U]
−>[TX:163C2734−0105−4000−E024−5B3B090A571D, state =
Esperando 5348 milisegundos, mode = U]
−>[TX:163C328C−0105−4000−E114−5B3B090A571D, state =
Esperando 1402 milisegundos, mode = U]
try {
...
}
catch (ObjectGridException oe) {
Throwable Root = findRootCause( oe );
if (Root instanceof LockTimeoutException) {
LockTimeoutException lte = (LockTimeoutException)Root;
System.out.println(lte.getLockRequestQueueDetails());
}
}
Solución: una excepción LockTimeoutException evita posibles puntos muertos en la aplicación. Una excepción de este tipo se genera cuando la excepción espera un periodo de tiempo establecido. Puede establecer el periodo de tiempo que espera una excepción utilizando el método setLockTimeout(int), que está disponible para la BackingMap. Si no existe realmente un punto muerto en la aplicación, ajuste el tiempo de espera de bloqueo para evitar la LockTimeoutException.
ObjectGrid objGrid = new ObjectGrid();
BackingMap bMap = objGrid.defineMap("MapName");
bMap.setLockTimeout(30);
Utilice el ejemplo codificado anterior para establecer las propiedades de ObjectGrid y de correlación. Si crea ObjectGrid a partir de un archivo XML, establezca el atributo LockTimeout en el elemento backingMap. A continuación se muestra un ejemplo de un valor LockTimeout de correlación de 30 segundos.
<backingMap name="MapName" lockStrategy="PESSIMISTIC" lockTimeout="30">
Descripción: los escenarios siguientes describen cómo se pueden producir puntos muertos cuando se accede a una sola clave utilizando un bloqueo S que se actualiza posteriormente. Cuando esto se produce desde dos transacciones que se ejecutan simultáneamente, se produce un punto muerto.
Hebra 1 | Hebra 2 | ||
---|---|---|---|
1 | session.begin() | session.begin() | Cada hebra establece una transacción independiente. |
2 | map.get(key1) | map.get(key1) | Se otorga el bloqueo S a las dos transacciones para key1. |
3 | map.update(Key1,v) | No se produce un bloqueo U. La actualización se realiza en la memoria caché transaccional. | |
4 | map.update(key1,v) | No se produce un bloqueo U. La actualización se realiza en la memoria caché transaccional. | |
5 | session.commit() | Bloqueado: el bloqueo S de key1 no se puede actualizar a un bloqueo X porque la hebra 2 tiene un bloqueo S. | |
6 | session.commit() | Punto muerto: el bloqueo S de key1 no se puede actualizar a un bloqueo X porque la hebra 1 tiene un bloqueo S. |
Hebra 1 | Hebra 2 | ||
---|---|---|---|
1 | session.begin() | session.begin() | Cada hebra establece una transacción independiente. |
2 | map.get(key1) | Se otorga el bloqueo S para key1. | |
3 | map.getForUpdate(key1,v) | El bloqueo S se actualiza a un bloqueo U para key1. | |
4 | map.get(key1) | Se otorga el bloqueo S para key1. | |
5 | map.getForUpdate(key1,v) | Bloqueado: la hebra 1 ya tiene el bloqueo U. | |
6 | session.commit() | Punto muerto: el bloqueo U de key1 no se puede actualizar. | |
7 | session.commit() | Punto muerto: no se puede actualizar el bloqueo S para la clave key1. |
Hebra 1 | Hebra 2 | ||
---|---|---|---|
1 | session.begin() | session.begin() | Cada hebra establece una transacción independiente. |
2 | map.get(key1) | Se otorga el bloqueo S para key1. | |
3 | map.getForUpdate(key1,v) | El bloqueo S se actualiza a un bloqueo U para key1. | |
4 | map.get(key1) | Se otorga el bloqueo S para key1. | |
5 | map.getForUpdate(key1,v) | Bloqueado: la hebra 1 ya tiene el bloqueo U. | |
6 | session.commit() | Punto muerto: el bloqueo U de key1 no se puede actualizar a un bloqueo X porque la hebra 2 tiene un bloqueo S. |
Hebra 1 | Hebra 2 | ||
---|---|---|---|
1 | session.begin() | session.begin() | Cada hebra establece una transacción independiente. |
2 | map.getForUpdate(key1) | Se otorga el bloqueo U a la hebra 1 para key1. | |
3 | map.getForUpdate(key1) | Se bloquea la solicitud de bloqueo U. | |
4 | map.update(key1,v) | <bloqueado> | |
5 | session.commit() | <bloqueado> | El bloqueo U de key1 puede actualizarse correctamente a un bloqueo X. |
6 | <liberado> | El bloqueo U se otorga finalmente a key1 para la hebra 2. | |
7 | map.update(key2,v) | Se otorga el bloqueo U a la hebra 2 para key2. | |
8 | session.commit() | El bloqueo U de key1 puede actualizarse correctamente a un bloqueo X. |
Descripción: este escenario describe lo que sucede si dos transacciones intentan actualizar la misma entrada directamente y mantienen bloqueos S a otras entradas.
Hebra 1 | Hebra 2 | ||
---|---|---|---|
1 | session.begin() | session.begin() | Cada hebra establece una transacción independiente. |
2 | map.get(key1) | map.get(key1) | Se otorga el bloqueo S a las dos transacciones para key1. |
3 | map.get(key2) | map.get(key2) | Se otorga el bloqueo S a las dos transacciones para key2. |
4 | map.update(key1,v) | No se produce un bloqueo U. La actualización se realiza en la memoria caché transaccional. | |
5 | map.update(key2,v) | No se produce un bloqueo U. La actualización se realiza en la memoria caché transaccional. | |
6. | session.commit() | Bloqueado: el bloqueo S de key1 no se puede actualizar a un bloqueo X porque la hebra 2 tiene un bloqueo S. | |
7 | session.commit() | Punto muerto: el bloqueo S de key2 no se puede actualizar porque la hebra 1 tiene un bloqueo S. |
Hebra 1 | Hebra 2 | ||
---|---|---|---|
1 | session.begin() | session.begin() | Cada hebra establece una transacción independiente. |
2 | map.getForUpdate(key1) | Se otorga el bloqueo U a la transacción de hebra 1 para key1. | |
3 | map.getForUpdate(key1) | Se bloquea la solicitud de bloqueo U. | |
4 | map.get(key2) | <bloqueado> | Se otorga el bloqueo S a la hebra 1 para key2. |
5 | map.update(key1,v) | <bloqueado> | |
6 | session.commit() | <bloqueado> | El bloqueo U de key1 puede actualizarse correctamente a un bloqueo X. |
7 | <liberado> | El bloqueo U se otorga finalmente a key1 para la hebra 2. | |
8 | map.get(key2) | Se otorga el bloqueo S a la hebra 2 para key2. | |
9 | map.update(key2,v) | Se otorga el bloqueo U a la hebra 2 para key2. | |
10 | session.commit() | El bloqueo U de key1 puede actualizarse correctamente a un bloqueo X. |
Hebra 1 | Hebra 2 | ||
---|---|---|---|
1 | session.begin() | session.begin() | Cada hebra establece una transacción independiente. |
2 | map.getforUpdate(key1) | map.getForUpdate(key2) | Se otorgan correctamente bloqueos U para key1 y key2. |
3 | map.get(key2) | map.get(key1) | Se otorga el bloqueos S para key1 y key2. |
4 | map.update(key1,v) | map.update(key2,v) | |
5 | session.commit() | El bloqueo U no se puede actualizar a un bloqueo X porque la hebra 2 tiene un bloqueo S. | |
6 | session.commit() | El bloqueo U no se puede actualizar a un bloqueo X porque la hebra 1 tiene un bloqueo S. |