Analizando Deadocks – la vieja forma

En la versión 9.7, DB2 comenzó a ofrecer un nuevo método de monitorización para el interbloqueo (deadlocks). Aunque esta publicación describe la forma «antigua», este método también funciona en db2 9.7. Los monitores de eventos Detailedeadlock han quedado en desuso, pero aún no se han eliminado. Esto significa que incluso en 9.7, aún puede crearlos y trabajar con ellos.

Si está confundido acerca de la diferencia entre los deadlocks y los lock timeouts, lea primero mi publicación en Deadlocks VS. Lock timeouts.

Crear el monitor de eventos de punto muerto

Una de las cosas más críticas aquí es que debe tener el monitor de eventos detailedeadlock creado y funcionando antes de encontrarse con un problema. Por defecto (incluso en 9.7), db2 tiene uno llamado simplemente «db2detaildeadlock». El único problema es que puede quedarse sin espacio con bastante rapidez. Como resultado, lo creo cada vez, utilizando esta sintaxis (por supuesto, necesitará una conexión a la base de datos):

db2 "create event monitor my_detaildeadlock for deadlocks with details write to file 'my_detaildeadlock' maxfiles 2000 maxfilesize 10000 blocked append autostart"
DB20000I  The SQL command completed successfully.

Además, hay que crear manualmente el directorio para el monitor de eventos. Va en el subdirectorio «db2event» de la ruta de la base de datos, por lo que en mi último ejemplo, utilicé algo así para crearlo:

mkdir /db_data/db2inst1/NODE0000/SQL00002/db2event/my_detaildeadlock

Y luego hay que activar el nuevo y eliminar el viejo:

db2 "set event monitor ros_detaildeadlock state=1"
DB20000I  The SQL command completed successfully.

db2 "set event monitor db2detaildeadlock state=0"
DB20000I  The SQL command completed successfully.

db2 "drop event monitor db2detaildeadlock"
DB20000I  The SQL command completed successfully.

Finalmente, usted querrá verificar el estado del monitor de eventos recién creado:

> db2 "select substr(evmonname,1,30) as evmonname, EVENT_MON_STATE(evmonname) as state from syscat.eventmonitors with ur"

EVMONNAME                      STATE
------------------------------ -----------
ROS_DETAILDEADLOCK                       1

  1 record(s) selected.

1 significa estado activo y 0 significa no activo, por lo que esta es la salida que queremos.

Formateando y analizando los resultados

Ahora que tenemos el monitor de eventos en funcionamiento, ¿qué hacemos con él? Bueno, suponiendo que realmente tenga algunos puntos muertos o deadlocks (como puede ver a través del snapshot event monitor, usando db2top, db2pd, vistas administrativas de db2 o el comando get snapshot), querrá vaciar el monitor de eventos que hemos creado y convertir su contenido a un formato legible.

> db2 flush event monitor MY_DETAILDEADLOCK
DB20000I  The SQL command completed successfully.
> db2evmon -path /db_data/db2inst1/NODE0000/SQL00002/db2event/my_detaildeadlock >deadlocks.out

Reading /db_data/db2inst1/NODE0000/SQL00002/db2event/ros_detaildeadlock/00000000.evt ...

Su ruta puede ser diferente, por supuesto. Prefiero emplear la opción de ruta en db2evmon porque he tenido menos problemas con ella. Hay una opción para especificar el nombre de la base de datos y el del monitor de eventos pero sencillamente no me parece tan fiable.

Así que ahora hemos hecho la parte fácil. Sí, así es, esa es la parte fácil. Dependiendo de la cantidad de puntos muertos, ahora puede tener un archivo gigante. Creo recordar haber analizado un fichero de 15 GB de una sola vez. Aquí hay algunos fragmentos de la salida para dar una idea de lo que está viendo:

379) Deadlock Event ...
  Deadlock ID:   20
  Number of applications deadlocked: 2
  Deadlock detection time: 01/03/2012 14:06:13.425034
  Rolled back Appl participant no: 2
  Rolled back Appl Id: 172.19.10.61.37259.120103200006
  Rolled back Appl seq number: : 0009
...
381) Deadlocked Connection ...
  Deadlock ID:   20
  Participant no.: 2
  Participant no. holding the lock: 1
  Appl Id: 172.19.10.61.37259.120103200006
  Appl Seq number: 00009
  Tpmon Client Workstation: spp27comm02x
  Appl Id of connection holding the lock: 172.19.10.61.62895.120103194755
  Seq. no. of connection holding the lock: 00001
  Lock wait start time: 01/03/2012 14:06:03.651592
  Lock Name       : 0x02000C1A1500BCE31800000052
  Lock Attributes : 0x00000000
  Release Flags   : 0x00000001
  Lock Count      : 1
  Hold Count      : 0
  Current Mode    : none
  Deadlock detection time: 01/03/2012 14:06:13.425119
  Table of lock waited on      : USERS
  Schema of lock waited on     : WSCOMUSR
  Data partition id for table  : 0
  Tablespace of lock waited on : USERSPACE1
  Type of lock: Row
  Mode of lock: X   - Exclusive
  Mode application requested on lock: NS  - Share (and Next Key Share)
  Node lock occured on: 0
  Lock object name: 106899963925
  Application Handle: 47264
  Deadlocked Statement:
    Type     : Dynamic
    Operation: Fetch
    Section  : 2
    Creator  : NULLID
    Package  : SYSSH200
    Cursor   : SQL_CURSH200C2
    Cursor was blocking: FALSE
    Text     : SELECT T1.STATE, T1.MEMBER_ID, T1.OPTCOUNTER, T1.TYPE, T2.FIELD2, T2.REGISTRATIONUPDATE, T2.FIELD3, T2.LASTORDER, T2.LANGUAGE_ID, T2.PREVLASTSESSION, T2.SETCCURR, T2.DN, T2.REGISTRATIONCANCEL, T2.LASTSESSION, T2.REGISTRATION, T2.FIELD1, T2.REGISTERTYPE, T2.PROFILETYPE, T2.PERSONALIZATIONID FROM MEMBER  T1, USERS  T2 WHERE T1.TYPE = 'U' AND T1.MEMBER_ID = T2.USERS_ID AND T1.MEMBER_ID = ?
  List of Locks:
...
383) Deadlocked Connection ...
  Deadlock ID:   20
  Participant no.: 1
  Participant no. holding the lock: 2
  Appl Id: 172.19.10.61.62895.120103194755
  Appl Seq number: 00905
  Tpmon Client Workstation: spp27comm02x
  Appl Id of connection holding the lock: 172.19.10.61.37259.120103200006
  Seq. no. of connection holding the lock: 00001
  Lock wait start time: 01/03/2012 14:06:03.657097
  Lock Name       : 0x02000D0E2F00F8D61800000052
  Lock Attributes : 0x00000000
  Release Flags   : 0x40000000
  Lock Count      : 1
  Hold Count      : 0
  Current Mode    : U   - Update
  Deadlock detection time: 01/03/2012 14:06:13.425274
  Table of lock waited on      : MEMBER
  Schema of lock waited on     : WSCOMUSR
  Data partition id for table  : 0
  Tablespace of lock waited on : USERSPACE1
  Type of lock: Row
  Mode of lock: NS  - Share (and Next Key Share)
  Mode application requested on lock: X   - Exclusive
  Node lock occured on: 0
  Lock object name: 106685792303
  Application Handle: 47206
  Deadlocked Statement:
    Type     : Dynamic
    Operation: Execute
    Section  : 25
    Creator  : NULLID
    Package  : SYSSH200
    Cursor   : SQL_CURSH200C25
    Cursor was blocking: FALSE
    Text     : UPDATE MEMBER  SET STATE = ?, OPTCOUNTER = ? WHERE MEMBER_ID = ? AND OPTCOUNTER = ?
  List of Locks:
...

He eliminado la lista de bloqueos debido a la longitud, y también las entradas en los eventos de conexión, pero no he alterado la salida real aquí.

La «Deadlock ID» nos permite identificar en qué punto muerto participó este. Los puntos muertos más frecuentemente involucran 2 conexiones, pero pueden involucrar 3, 4, 5 o incluso más.

Si observa el «Participant no» tanto en la sección «Deadlock Event» como en las secciones de «Deadlocked Connection» y «Rolled back Appl participant no» en la sección «Deadlock Event», puede comprender qué declaración se deshizo con rollback y cuál se permitió continuar.

Hay mucha más información útil para analizar, la mayor parte es bastante obvia en su significado.

Es bueno revisar y determinar si las mismas sentencias estuvieron involucradas en puntos muertos una y otra vez, y qué sentencias estuvieron involucradas con mayor frecuencia en un punto muerto. También es bueno analizar la duración de los puntos muertos: Un resumen por hora es muy útil para ayudar a determinar si se limitaron a un período de tiempo específico. También puede ser interesante resumir por tabla para ver si una tabla en particular está frecuentemente involucrada.

¿Qué hacer con el análisis?

Lo primero que debe hacer con lo que encuentre es proporcionar el código SQL a sus desarrolladores. Deben ser capaces de comprender de dónde proviene ese SQL en su aplicación, y deberían poder proponer ideas para reducir el bloqueo.

Recuerde que el interbloqueo, punto muerto o deadlock es un problema de aplicación cuyos síntomas aparecen en la base de datos. Todo lo que puede hacer para reducir el bloqueo a nivel de base de datos es:

  1. Mantener runstats actualizadas
  2. Establecer las siguientes variables de registro de db2, SOLO SI SU APLICACIÓN LOS APOYA EXPLÍCITAMENTE:
    • DB2_SKIPINSERTED
    • DB2_SKIPDELETED
    • DB2_EVALUNCOMMITTED

Aumentar LOCKLIST no ayudará con el interbloqueo a menos que también esté viendo escaladas de bloqueo.

References:

Info Center entry on deprecation of detaildeadlock event monitor: http://www.ibm.com/support/knowledgecenter/SSEPGG_9.7.0/com.ibm.db2.luw.wn.doc/doc/i0054715.html

 

Info Center entry on db2evmon:

http://www.ibm.com/support/knowledgecenter/SSEPGG_9.7.0/com.ibm.db2.luw.admin.cmd.doc/doc/r0002046.html

 

José Barón
José Barón
Artículos: 6

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Este sitio usa Akismet para reducir el spam. Aprende cómo se procesan los datos de tus comentarios.