Pyxis Logo
Inicio / Formación IBM / Artículo técnico

Uso del formato JSON en db2diag

Cómo db2diag -json de Db2 12.1.3.0, combinado con jq, permite analizar eventos de diagnóstico de forma estructurada y generar salidas tabulares limpias.

20 min de lectura
Publicado 2026-05-12
Pyxis editorial team
Califique este artículo
Calificación media: Sin calificación
Su calificación: Sin calificación
visualizaciones: 0
Salida de diagnóstico Db2 como JSON estructurado y salida tabular con jq

db2diag.log es el registro central de diagnóstico de una instancia Db2 y, junto con el log de notificación, es uno de los primeros lugares que conviene revisar cuando hay fallos de conexión, problemas de locks, deadlocks o comportamientos inesperados del motor Db2. El problema de siempre ha sido el acceso: texto libre, varias formas de salida, campos posicionales y un parsing frágil cuando se quiere automatizar el análisis.

Db2 12.1.3.0 introdujo la opción -json en db2diag. Cuando se usa, la salida del comando pasa a ser JSON Lines: un objeto JSON por línea, con campos estructurados que pueden filtrarse y agregarse con jq. El objetivo de este artículo es mostrar lo que se puede hacer con ese formato JSON. Los lock timeouts y los deadlocks son solo el ejemplo práctico utilizado para hacer visible la diferencia entre texto libre y datos estructurados.

1. Objetivos e introducción de la lab

Al finalizar esta lab deberías poder:

  • entender qué tipo de análisis se vuelve más fácil con db2diag -json
  • identificar los parámetros que controlan el registro de diagnóstico y de eventos de lock
  • entender el enfoque tradicional de db2diag y sus limitaciones
  • usar db2diag -json para inspeccionar los campos disponibles en un mensaje concreto
  • transformar la salida JSON en tablas legibles con jq y column
  • crear una plantilla reutilizable para repetir el análisis más adelante

La idea es mostrar por qué la salida JSON mejora el triaje, la correlación y la automatización cuando Db2 empieza a producir eventos de diagnóstico difíciles de leer manualmente.

2. Lo que vas a necesitar para ejecutar la lab

Vas a necesitar:

  • Db2 LUW 12.1.3.0 o superior
  • Un sistema Linux. Presta atención a las versiones mínimas admitidas. Para Red Hat usa 9.4 o superior; para Ubuntu usa 22.04.5 o superior.
  • Acceso a la cuenta propietaria de la instancia Db2
  • jq
  • column
  • awk, grep, sed, bash y utilidades estándar de shell

Si Db2 no está instalado, obténlo desde el portal oficial de descargas de software de IBM o desde el mecanismo de distribución asociado a tu licencia o entitlement. Db2 Community Edition es suficiente.

Si hace falta, instala Db2 y crea la instancia que vas a utilizar en la lab.

Para instalar el software auxiliar, ejecuta:

En RHEL, Rocky, AlmaLinux, SLES

sudo dnf install -y jq util-linux

En Debian o distribuciones basadas en Debian

sudo apt-get install -y jq util-linux

Los comandos siguientes deben ejecutarse con la cuenta propietaria de la instancia Db2.

Los parámetros que vamos a modificar son:

ParámetroNivelFunción
DIAGLEVELDBM CFGControla qué severidades se escriben en db2diag.log
NOTIFYLEVELDBM CFGControla qué eventos se escriben en el log de notificación
LOCKTIMEOUTDB CFGDefine cuánto puede durar la espera por un lock
DLCHKTIMEDB CFGDefine el intervalo de detección de deadlocks en milisegundos
MON_LCK_MSG_LVLDB CFGControla el registro de deadlocks, lock timeouts y lock waits

Para esta lab:

ValorEfecto
DIAGLEVEL 3Garantiza que se registren eventos Warning, Error y Severe
NOTIFYLEVEL 3Mantiene útil el log de notificación para operaciones normales
LOCKTIMEOUT 5Fuerza un lock timeout rápido
DLCHKTIME 1000Hace que la detección de deadlocks ocurra antes de que venza un timeout de 5 segundos
MON_LCK_MSG_LVL 3Registra deadlocks, lock timeouts y lock waits en db2diag.log

3. Mecanismos tradicionales de visualización del diagnóstico

db2diag

El comando db2diag sigue siendo la herramienta central para leer db2diag.log. Permite filtrar por severidad y por intervalo temporal y otros criterios, ofrece opciones básicas de formato y búsqueda, y es útil cuando investigas un incidente en tiempo real.

Ejemplo:

db2diag -t "$(date -d '1 hour ago' '+%Y-%m-%d-%H.%M.%S')" -l Warning,Error,Severe

Sin embargo, tiene algunas limitaciones:

  • es difícil agregar por pid, tid, componente o función sin parsing adicional
  • los mensajes con campos anidados requieren regex u otras técnicas frágiles de parsing
  • grep trabaja línea a línea y, aunque pidas líneas adyacentes, no entiende el contexto completo de un bloque de diagnóstico
  • exportar a CSV o correlacionar eventos requiere más trabajo del que debería

Vistas administrativas

Las vistas administrativas, como SYSIBMADM.PDLOGMSGS_LAST24HOURS, son útiles para monitorización operativa. Ofrecen flexibilidad SQL, pero leen el log de notificación y no db2diag.log. Son buenas para eventos de arranque, parada y eventos operativos generales.

Ejemplo:

db2 connect to DIAGJSON
db2 "SELECT TIMESTAMP, MSGSEVERITY, SUBSTR(MSG,1,256) AS MSG FROM SYSIBMADM.PDLOGMSGS_LAST24HOURS ORDER BY TIMESTAMP DESC FETCH FIRST 20 ROWS ONLY"

Limitaciones principales:

  • dependen de que Db2 esté operativo
  • no muestran todos los detalles internos del diagnóstico

Table functions y monitorización SQL

Las table functions y las vistas de monitorización ayudan con dashboards y observabilidad continua, pero también dependen de una instancia Db2 sana. Son muy útiles cuando la instancia y la base de datos están arriba, pero mucho menos cuando no lo están, que es precisamente cuando la información de diagnóstico importa más.

En resumen:

  • db2diag es la fuente más cercana al evento real
  • las vistas y funciones SQL son buenas para observabilidad cuando el sistema está sano

4. Soporte de salida JSON en Db2 (db2diag -json)

A partir de Db2 12.1.3.0, puedes añadir -json a db2diag.

Eso cambia dos cosas:

  • la salida pasa a ser JSON Lines, con un objeto JSON por línea
  • los campos pasan a ser estructurados y pueden consumirse sin parsing de texto libre

Las ventajas son claras:

  • los datos se entregan en un formato estructurado que las plataformas de observabilidad pueden consumir mejor
  • herramientas que procesan JSON, como jq, pueden explorar los datos con flexibilidad

Para el tipo de análisis que cubre este artículo, JSON no sustituye al db2diag clásico; lo complementa. Usa el formato tradicional para una inspección rápida y JSON cuando necesites más flexibilidad de filtrado, parsing y formato.

5. Escenario y ejecución de la lab

Vamos a crear una base de datos, objetos de schema y datos de ejemplo, y luego generaremos varios lock timeouts y un escenario de deadlock para producir registros de contención en db2diag.log. Usaremos la nueva capacidad de formato JSON para inspeccionar la información de diagnóstico resultante.

Establecer la configuración necesaria a nivel de base de datos e instancia

Empieza creando la base de datos y estableciendo los parámetros necesarios de la instancia y de la base de datos Db2.

db2 create database DIAGJSON
db2 connect to DIAGJSON
db2 "UPDATE DB CFG FOR DIAGJSON USING LOCKTIMEOUT 5 MON_LCK_MSG_LVL 3"
db2 update dbm cfg using DIAGLEVEL 3 NOTIFYLEVEL 3
db2stop force
db2start

Para confirmar los valores, ejecuta:

db2 get dbm cfg | grep -iE "diaglevel|notifylevel"
db2 get db cfg for DIAGJSON | grep -iE "locktimeout|mon_lck_msg_lvl"

Crea los objetos de schema y carga los datos de ejemplo:

db2 connect to DIAGJSON
db2 "CREATE SCHEMA app"
db2 "CREATE TABLE app.accounts (id INTEGER NOT NULL, balance DECIMAL(10,2), PRIMARY KEY (id))"
db2 "INSERT INTO app.accounts VALUES (1, 5000.00)"
db2 "INSERT INTO app.accounts VALUES (2, 3000.00)"
db2 commit
db2 connect reset

Generación del problema y de la evidencia de diagnóstico

Vamos a generar un lock timeout. Para ello iniciamos dos sesiones. Una sesión mantiene un lock y la otra intenta acceder a la fila bloqueada hasta que vence el tiempo de espera.

cat > /tmp/hold_lock.sh <<'EOF'
#!/bin/bash
db2 connect to DIAGJSON
db2 +c "UPDATE app.accounts SET balance = balance - 100 WHERE id = 1"
sleep 30
db2 commit
db2 connect reset
EOF
chmod +x /tmp/hold_lock.sh

bash /tmp/hold_lock.sh &
LOCK_PID=$!
sleep 3

db2 connect to DIAGJSON
db2 "UPDATE app.accounts SET balance = balance + 100 WHERE id = 1"
kill $LOCK_PID 2>/dev/null
wait $LOCK_PID 2>/dev/null
db2 connect reset

Ahora generaremos un deadlock. Usaremos dos sesiones que actualizan filas de la misma tabla en orden opuesto. Ninguna de las dos podrá adquirir el segundo lock porque la otra sesión ya mantiene la fila necesaria.

Para esta prueba, desactivamos el timeout por sesión con CURRENT LOCK TIMEOUT = -1 y reducimos DLCHKTIME a 1000, para que la detección del deadlock ocurra antes de que el escenario se degrade en un timeout.

db2 connect to DIAGJSON
db2 "UPDATE DB CFG FOR DIAGJSON USING DLCHKTIME 1000"
db2 connect reset

cat > /tmp/deadlock_a.sh <<'EOF'
#!/bin/bash
db2 connect to DIAGJSON
db2 "SET CURRENT LOCK TIMEOUT -1"
db2 +c "UPDATE app.accounts SET balance = balance - 100 WHERE id = 1"
sleep 2
db2 +c "UPDATE app.accounts SET balance = balance + 100 WHERE id = 2"
db2 rollback
db2 connect reset
EOF

cat > /tmp/deadlock_b.sh <<'EOF'
#!/bin/bash
db2 connect to DIAGJSON
db2 "SET CURRENT LOCK TIMEOUT -1"
db2 +c "UPDATE app.accounts SET balance = balance - 100 WHERE id = 2"
sleep 2
db2 +c "UPDATE app.accounts SET balance = balance + 100 WHERE id = 1"
db2 rollback
db2 connect reset
EOF

chmod +x /tmp/deadlock_a.sh /tmp/deadlock_b.sh
bash /tmp/deadlock_a.sh &
bash /tmp/deadlock_b.sh &
wait

Después de la prueba, restaura el intervalo de detección por defecto si quieres volver al comportamiento habitual:

db2 connect to DIAGJSON
db2 "UPDATE DB CFG FOR DIAGJSON USING DLCHKTIME 10000"
db2 connect reset

Ahora podemos pasar al formato JSON. La salida JSON de db2diag produce líneas en las que cada línea es un objeto JSON independiente.

Si el timeout por sesión sigue por debajo del intervalo de detección de deadlocks, Db2 puede devolver SQL0911N con reason code 68 y registrar solo la contención como ADM5506W. Por eso el escenario de deadlock siguiente ajusta CURRENT LOCK TIMEOUT y DLCHKTIME antes de repetir la prueba.

El archivo de schema JSON que define la estructura esperada está en ~/sqllib/misc/db2diag.schema.json:

Inspecciónalo directamente:

sed -n '1,80p' ~/sqllib/misc/db2diag.schema.json

Ya tenemos una idea de la estructura del schema antes de mirar la salida real de db2diag.

Examina un mensaje concreto de lock timeout y compáralo con el schema:

db2diag -level Warning -g msg:=ADM5506W -json -V > /tmp/adm5506w.jsonl
head -1 /tmp/adm5506w.jsonl

Ahora usa jq con pretty print para el mismo efecto:

db2diag -level Warning -g msg:=ADM5506W -json -V | head -1 | jq '.'

Vamos a listar los nombres de los campos de nivel superior disponibles en la primera entrada que corresponda a ADM5506W:

db2diag -level Warning -g msg:=ADM5506W -json -V |
jq -nr 'first(inputs) | keys_unsorted[]'

Esta técnica es útil para descubrir rápidamente qué campos existen sin depender de leer manualmente el texto completo de un mensaje.

Ahora haremos el ejemplo más práctico. Filtramos con parámetros de db2diag y luego usamos jq y column para obtener una tabla limpia en el terminal. column se usa para alinear las columnas en el terminal. Si vas a escribir la salida en un archivo, puedes omitir column.

El ejemplo extrae campos estructurados del JSON y, al mismo tiempo, hace parsing de partes textuales dentro de message. Es mucho más estable que intentar hacer lo mismo con grep sobre la salida de db2diag.

db2diag -level Warning -g msg:=ADM5506W -json -V |
jq -nr '
  def msg: (.message // "" | gsub("[\n ]+"; " "));
  def cap($re): (msg | capture($re).v? // "-");

  ["timestamp","timezone","level","pid","tid","process","instance","member","database","apphdl","appid","uowid","actid","authid","hostname","eduid","eduname","function","probe","event_type","lock_id","event_ts","affected_app","workload","affected_appid","role"],

  (
    inputs
    | [
        (.timestamp // "-"),
        (.timezone // "-"),
        (.level // "-"),
        (.pid // "-"),
        (.tid // "-"),
        (.process // "-"),
        (.instance // "-"),
        (.member // "-"),
        (.database // "-"),
        (.apphdl // "-"),
        (.appid // "-"),
        (.uowid // "-"),
        (.actid // "-"),
        (.authid // "-"),
        (.hostname // "-"),
        (.eduid // "-"),
        (.eduname // "-"),
        (.function // "-"),
        (.probe // "-"),
        cap("type of the event is: \"(?<v>[^\"]+)\""),
        cap("identifier of the lock on which this event happened is: \"(?<v>[^\"]+)\""),
        cap("timestamp of the event is: \"(?<v>[^\"]+)\""),
        cap("affected application is named \"(?<v>[^\"]+)\""),
        cap("workload named \"(?<v>[^\"]+)\""),
        cap("application identifier is: \"(?<v>[^\"]+)\""),
        cap("role that this application plays with respect to this lock is: \"(?<v>[^\"]+)\"")
      ]
  )
  | @tsv
' |
column -t -s $'\t'

Cuando repitas el análisis más de una vez, conviene guardar la especificación en un archivo y reutilizarla desde jq. Crea el archivo de definiciones:

mkdir -p ~/db2diag-jq
vi ~/db2diag-jq/adm5506w-locks.jq

Pega el siguiente contenido en el archivo:

def msg: (.message // "" | gsub("[\n ]+"; " "));
def cap($re): (msg | capture($re).v? // "-");

["timestamp","timezone","level","pid","tid","process","instance","member","database","apphdl","appid","uowid","actid","authid","hostname","eduid","eduname","function","probe","event_type","lock_id","event_ts","affected_app","workload","affected_appid","role"],

(
  inputs
  | [
      (.timestamp // "-"),
      (.timezone // "-"),
      (.level // "-"),
      (.pid // "-"),
      (.tid // "-"),
      (.process // "-"),
      (.instance // "-"),
      (.member // "-"),
      (.database // "-"),
      (.apphdl // "-"),
      (.appid // "-"),
      (.uowid // "-"),
      (.actid // "-"),
      (.authid // "-"),
      (.hostname // "-"),
      (.eduid // "-"),
      (.eduname // "-"),
      (.function // "-"),
      (.probe // "-"),
      cap("type of the event is: \"(?<v>[^\"]+)\""),
      cap("identifier of the lock on which this event happened is: \"(?<v>[^\"]+)\""),
      cap("timestamp of the event is: \"(?<v>[^\"]+)\""),
      cap("affected application is named \"(?<v>[^\"]+)\""),
      cap("workload named \"(?<v>[^\"]+)\""),
      cap("application identifier is: \"(?<v>[^\"]+)\""),
      cap("role that this application plays with respect to this lock is: \"(?<v>[^\"]+)\"")
    ]
)
| @tsv

Repite el ejemplo anterior, esta vez usando el archivo en lugar de pasar todos los parámetros por línea de comandos:

db2diag -level Warning -g msg:=ADM5506W -json -V |
jq -nr -f ~/db2diag-jq/adm5506w-locks.jq |
column -t -s $'\t'

6. Consideraciones finales y resumen

La salida tradicional de db2diag es adecuada para una inspección rápida, pero tiene limitaciones. Con db2diag -json, cada evento pasa a ser un objeto estructurado, lo que facilita:

  • contar eventos por componente
  • agrupar por pid o tid
  • exportar a TSV o CSV
  • integrar con automatización y sistemas de observabilidad

7. Cleanup

Al terminar la lab, ejecuta:

db2 connect reset
db2 drop database DIAGJSON

Elimina también los archivos temporales:

rm -f /tmp/hold_lock.sh /tmp/deadlock_a.sh /tmp/deadlock_b.sh
rm -f ~/db2diag-jq/adm5506w-locks.jq

Documentación útil de IBM

Para profundizar, las referencias de IBM más útiles para este tema son:

Más en esta área

Más en esta área

Volver a formación
Categoría de artículos

Artículos de Db2 LUW

Consulta todos los artículos técnicos de Db2 LUW en una sola página de categoría.

Abrir categoría Db2 LUW