sábado, 26 de septiembre de 2026

NMON en Oracle AI Database 26ai: investigando el nuevo observador de la red

 


Oracle AI Database 26ai incorpora numerosos cambios que resultan inmediatamente visibles para administradores y desarrolladores: nuevas capacidades relacionadas con inteligencia artificial, vectores, automatización y observabilidad. Sin embargo, existen otros cambios que trabajan silenciosamente en segundo plano y que probablemente pasen inadvertidos para muchos administradores.

Uno de ellos es NMON (Network Monitor Process).

Oracle lo incorpora como un proceso background encargado de tareas relacionadas con la monitorización de red. A primera vista podría parecer simplemente otro proceso auxiliar agregado a la larga lista de procesos internos de Oracle Database.

Pero cuando comenzamos a investigar su comportamiento en una instalación real de Oracle AI Database 26ai, encontramos algo bastante más interesante.

NMON mantiene su propia infraestructura de monitorización, trabaja con estadísticas del sistema operativo y de las interfaces de red, conserva información histórica y permite que esos datos sean extraídos mediante un paquete PL/SQL denominado DBMS_NETMON.

En este artículo vamos a alejarnos deliberadamente de una simple descripción de la documentación y observar qué está haciendo realmente NMON.

Esto aplica para una base de datos Oracle AI Database 26ai, 23.26.3, corriendo en Kernel de Oracle Linux 6.12.0-206.104.4.4.el9uek.x86_64, Oracle Linux Server 9.8


Encontrando NMON

Podemos localizar el proceso directamente desde la base de datos:

SET LINESIZE 220
COLUMN program   FORMAT A30
COLUMN tracefile FORMAT A120

SELECT pid,
       spid,
       pname,
       program,
       tracefile
FROM   v$process
WHERE  pname = 'NMON';

En nuestro laboratorio Oracle AI Database 26ai obtuvimos:

PID  SPID   PNAME  PROGRAM
---  -----  -----  --------------------------------
30   54272  NMON   oracle@oracle-server-26ai (NMON)

El proceso tiene además su propio archivo de trace:

/u01/app/oracle/diag/rdbms/cdb/cdb/trace/cdb_nmon_54272.trc

El detalle es interesante porque el SPID del proceso:

54272

coincide con el sufijo:

cdb_nmon_54272.trc

NMON es, por tanto, un verdadero proceso background de Oracle con su propia presencia en ADR y su propio mecanismo de diagnóstico.


DBMS_NETMON: la puerta de entrada a NMON

Oracle proporciona en 26ai el paquete:

DBMS_NETMON

Nuestra primera sorpresa apareció precisamente aquí.

Algunas aproximaciones iniciales basadas únicamente en ejemplos o interpretaciones de documentación no coincidían exactamente con la implementación instalada. Por eso decidimos consultar directamente DBA_ARGUMENTS.

Para conocer la firma real de SHOW_SERVICE_STATUS:

SELECT overload,
       position,
       argument_name,
       data_type,
       in_out,
       defaulted
FROM   dba_arguments
WHERE  owner        = 'SYS'
AND    package_name = 'DBMS_NETMON'
AND    object_name  = 'SHOW_SERVICE_STATUS'
ORDER BY overload, sequence;

En nuestra instalación 26ai encontramos que la función recibe solamente un argumento opcional:

SERVICE_CAT  BINARY_INTEGER IN

y devuelve VARCHAR2.

Por tanto, para obtener el estado general basta con:

SELECT DBMS_NETMON.SHOW_SERVICE_STATUS()
FROM dual;

El resultado es JSON.

Para hacerlo más legible podemos transformarlo mediante JSON_TABLE:

SELECT jt.service,
       jt.type,
       CASE jt.enabled
            WHEN 1 THEN 'ENABLED'
            ELSE 'DISABLED'
       END status
FROM JSON_TABLE(
       DBMS_NETMON.SHOW_SERVICE_STATUS(),
       '$[*]'
       COLUMNS (
          service VARCHAR2(50) PATH '$.Service',
          type    VARCHAR2(20) PATH '$.Type',
          enabled NUMBER       PATH '$.Enabled'
       )
     ) jt
ORDER BY jt.service,
         jt.type;

Nuestro resultado:

SERVICE              TYPE    STATUS
-------------------- ------- --------
IpIfEventStats       Event   ENABLED
IpIfEventStats       Stats   ENABLED
PerFlowEventStats    Event   DISABLED
PerFlowEventStats    Stats   DISABLED
SystemEventStats     Event   ENABLED
SystemEventStats     Stats   ENABLED

Aquí aparece la primera aproximación a la arquitectura de NMON.

Existen tres categorías claramente identificables:

SYSTEM
IPIF
PER-FLOW

En nuestra instalación, SYSTEM e IPIF se encuentran activos mientras que las estadísticas por flujo están globalmente deshabilitadas.


¿Quién consume estas estadísticas?

La siguiente función resulta todavía más interesante:

SELECT DBMS_NETMON.SHOW_CLIENT_STATUS()
FROM dual;

SHOW_CLIENT_STATUS devuelve un CLOB en formato JSON.

Podemos convertirlo nuevamente a información relacional:

SELECT jt.id,
       jt.name,
       CASE jt.event_enabled
           WHEN 1 THEN 'ENABLED'
           ELSE 'DISABLED'
       END AS event_status,
       CASE jt.stats_enabled
           WHEN 1 THEN 'ENABLED'
           ELSE 'DISABLED'
       END AS stats_status,
       jt.interval_value AS interval_ms,
       ROUND(jt.interval_value / 1000,1) AS interval_seconds
FROM JSON_TABLE(
       DBMS_NETMON.SHOW_CLIENT_STATUS(),
       '$[*]'
       COLUMNS (
          id             NUMBER        PATH '$.Id',
          name           VARCHAR2(100) PATH '$.Name',
          event_enabled  NUMBER        PATH '$.Event',
          stats_enabled  NUMBER        PATH '$.Stats',
          interval_value NUMBER        PATH '$.Interval'
       )
     ) jt
ORDER BY jt.name;

Aquí encontramos varios consumidores internos.

Entre ellos:

SQLNet flow client
LREG flow client

KSNMON IPIF generic stats trace client
KSNMON IPIF extended stats trace client
KSNMON client IPIF abnormal stats monitor

KSNMON client system statistics trace generation
KSNMON client system statistics event generation

La presencia de:

SQLNet flow client

es especialmente reveladora porque establece una relación explícita entre la infraestructura NMON y Oracle Net.

El cliente aparece configurado con estadísticas y eventos habilitados:

Event    ENABLED
Stats    ENABLED
Interval 30000 ms

Sin embargo, el servicio global PerFlowEventStats estaba deshabilitado en nuestro sistema.

Esto parece indicar que la configuración de los consumidores y la habilitación global de los servicios son mecanismos separados.

No debemos confundir que un cliente esté configurado para solicitar estadísticas con que el servicio productor correspondiente esté necesariamente activo.


Los intervalos de monitorización

Los clientes mostraron tres intervalos particularmente interesantes:

IPIF generic       5000 ms
SYSTEM            30000 ms
IPIF extended    120000 ms

Inicialmente esto sólo era información reportada por DBMS_NETMON.

Posteriormente pudimos comprobar esos intervalos directamente en el trace.

Las estadísticas IPIF aparecieron en:

03:22:29.847
03:22:34.847
03:22:39.847
03:22:44.847
03:22:49.847

Exactamente cada cinco segundos.

Las estadísticas SYSTEM aparecieron en:

03:22:43.799
03:23:13.799
03:23:43.799

Exactamente cada 30 segundos.

Es una excelente confirmación experimental de que los valores reportados por SHOW_CLIENT_STATUS están expresados en milisegundos.


Los parámetros ocultos de KSNMON

Buscando referencias internas encontramos además varios parámetros ocultos:

SELECT a.ksppinm AS parameter,
       b.ksppstvl AS value,
       a.ksppdesc AS description
FROM   x$ksppi a
JOIN   x$ksppcv b
       ON a.indx = b.indx
WHERE  LOWER(a.ksppinm) LIKE '%ksnmon%'
ORDER BY a.ksppinm;

Entre ellos aparecen:

_ksnmon_max_flow                  65535
_ksnmon_min_stats_interval_ms     5000
_ksnmon_service_enable_bitmask    2147483647

Las propias descripciones internas de Oracle resultan esclarecedoras:

KSNMON max number of flows monitored
KSNMON min stats report interval in ms
KSNMON service enable (a bit per service)

_ksnmon_max_flow=65535 demuestra que la infraestructura está preparada para mantener un número considerable de flujos.

No significa necesariamente que NMON esté monitorizando 65.535 conexiones en nuestro sistema. Es el máximo configurado internamente.

El segundo parámetro:

_ksnmon_min_stats_interval_ms = 5000

confirma además el intervalo mínimo de estadísticas de cinco segundos que habíamos observado.

Finalmente:

_ksnmon_service_enable_bitmask = 2147483647

equivale a:

0x7FFFFFFF

y Oracle lo describe como un bit por servicio.

No conocemos todavía el mapeo interno de esos bits y no resulta prudente intentar modificar ninguno de estos parámetros.

Son parámetros internos, no una interfaz de configuración soportada.


El descubrimiento más interesante: NMON conserva historia

El paquete contiene además:

DUMP_HISTORICAL_STATS

Consultando DBA_ARGUMENTS comprobamos su firma real:

LAST_SECOND BINARY_INTEGER IN DEFAULT

Por tanto podemos solicitar, por ejemplo, los últimos 60 segundos:

EXEC DBMS_NETMON.DUMP_HISTORICAL_STATS(60);

En nuestro laboratorio ejecutamos la llamada aproximadamente a:

27-SEP-2026 03:23:45 UTC

Inmediatamente el trace del proceso NMON fue actualizado.

La operación terminó mostrando:

Trace Bucket Dump End: KSNMON PRIVATE BUCKET


La expresión utilizada internamente por Oracle es significativa:

KSNMON PRIVATE BUCKET

Esto demuestra que NMON mantiene una estructura histórica interna desde la cual DUMP_HISTORICAL_STATS puede recuperar las muestras recientes y volcarlas al trace.


¿Qué está observando realmente NMON?

Aquí es donde la investigación se vuelve particularmente interesante.

Dentro del trace encontramos:

Statistics from "nstat -az"
difference w.r.t previous dump in brackets


Es decir, NMON está obteniendo estadísticas del stack de red de Linux equivalentes a las proporcionadas por:

nstat -az

Entre las métricas observadas encontramos:

IpInReceives
IpInDelivers
IpOutRequests
IpOutTransmits

TcpActiveOpens
TcpAttemptFails
TcpInSegs
TcpOutSegs
TcpOutRsts

UdpInDatagrams
UdpOutDatagrams

TcpExtDelayedACKs
TcpExtTCPPureAcks
TcpExtTCPHPAcks
TcpExtTCPKeepAlive
TcpExtTCPDelivered

IpExtInOctets
IpExtOutOctets


Esto significa que Oracle Database ahora dispone internamente de visibilidad sobre métricas que tradicionalmente un DBA tendría que investigar directamente desde Linux.


Valor absoluto y diferencia

NMON no se limita a conservar el contador.

Por ejemplo:

TcpActiveOpens  : 76960 [6]
TcpAttemptFails : 28996 [2]
TcpInSegs       : 928338 [57]
TcpOutSegs      : 788470 [67]


El primer número corresponde al valor acumulado.

El número entre corchetes representa, según el propio trace:

difference w.r.t previous dump

Esto es fundamental para diagnóstico.

NMON puede observar no sólo que:

TcpAttemptFails = 28996

sino que desde la muestra anterior ocurrieron:

[2]

intentos fallidos adicionales.

El mismo principio se aplica a paquetes, segmentos TCP, bytes y otros contadores.


NMON también observa cada interfaz

El componente IPIF descubrió automáticamente en nuestro servidor:

enp0s5
br-42b44ea9771b
docker0

incluyendo su índice, dirección IP y estado operacional.

Por ejemplo:

Interface enp0s5[Index 2]
Operational status UP
Bound IPs: 10.0.0.130

Para esa interfaz mantiene estadísticas como:

rx_bytes
rx_packets
tx_bytes
tx_packets

Una muestra concreta mostró:

rx_bytes   : 2322488244 [769]
rx_packets : 910881     [6]
tx_bytes   : 322593447  [629]
tx_packets : 761959     [7]


De nuevo tenemos:

contador acumulado [diferencia]

y las muestras se producen cada cinco segundos.


Un pequeño pico capturado por NMON

Durante la investigación encontramos una muestra particularmente ilustrativa:

rx_bytes   : 2322496872 [7143]
rx_packets : 910923     [25]

tx_bytes   : 322648644  [53998]
tx_packets : 762012     [37]


En la ventana de cinco segundos NMON detectó un incremento de aproximadamente:

RX  7 KB
TX 54 KB

No es una cantidad importante de tráfico.

Lo importante es demostrar que NMON conserva suficiente granularidad para detectar esa variación dentro de una ventana de apenas cinco segundos.


RDS también está dentro del radar

Otra línea particularmente interesante del trace es:

Statistics from "rdsinfo -c"


RDS —Reliable Datagram Sockets— tiene especial relevancia dentro de determinadas arquitecturas Oracle de alto rendimiento.

Por tanto, NMON no parece diseñado exclusivamente alrededor del tráfico TCP/IP convencional.

Su arquitectura contempla también la recopilación de información relacionada con RDS.

En nuestro laboratorio no observamos actividad RDS significativa, por lo que sería incorrecto extraer conclusiones adicionales sobre su funcionamiento únicamente con esta prueba.


Estadísticas extendidas de interfaz

Encontramos además una muestra IPIF diferente:

tx_kicks  : 742029 [204]
tx0_kicks : 742029 [204]

acompañada de:

cur idx: 20
prev idx: 20
max idx: 6200


Esta estructura es distinta de las estadísticas IPIF normales.

Sabemos además que existe un cliente:

KSNMON IPIF extended stats trace client

configurado con un intervalo de:

120000 ms

Resulta razonable investigar si ambos elementos están relacionados, pero todavía no tenemos evidencia suficiente para afirmarlo categóricamente.

Ésta es precisamente la diferencia entre observar el funcionamiento interno de Oracle y tratar de adivinarlo.


Una nueva capa de diagnóstico

Hasta ahora un DBA que investigaba problemas de conectividad normalmente debía correlacionar información procedente de diferentes lugares:

alert.log
listener.log
Oracle Net
V$SESSION
V$PROCESS
ss
netstat
nstat
ip
sar
tcpdump

NMON no sustituye estas herramientas.

Pero introduce algo conceptualmente importante: Oracle Database comienza a conservar su propia visión histórica del estado de la red del sistema operativo.

La arquitectura observada experimentalmente puede resumirse así:

 Oracle AI Database 26ai
                             |
                            NMON
                             |
                           KSNMON
                             |
              +--------------+--------------+
              |              |              |
           SYSTEM           IPIF           FLOW
              |              |              |
          30 segundos     5 segundos      SQLNet
              |              |
          nstat -az      Interfaces
          rdsinfo -c        Linux
              |              |
              +------+-------+
                     |
                     v
              Historical Stats
                     |
             KSNMON PRIVATE BUCKET
                     |
                     v
        DBMS_NETMON.DUMP_HISTORICAL_STATS
                     |
                     v
                NMON trace

¿Por qué puede ser importante para un DBA?

Pensemos en un incidente bastante común:

"Durante unos segundos las conexiones estuvieron lentas."

Cuando el DBA comienza a investigar veinte minutos después, el problema ya desapareció.

La base de datos puede conservar información de sesiones y waits. Linux puede conservar determinadas estadísticas acumuladas. Los logs pueden mostrar errores.

Pero normalmente reconstruir exactamente qué estaba ocurriendo en la red requiere correlacionar varias fuentes.

La existencia de un histórico NMON cambia parcialmente ese escenario.

Podríamos encontrarnos con una ventana donde:

TcpAttemptFails     aumenta
TcpOutRsts          aumenta
retransmisiones     aumentan
errores de interfaz aumentan

al mismo tiempo que Oracle registra un problema de conexión.

Eso puede ayudar a responder una pregunta que tradicionalmente resulta complicada:

¿el problema estaba dentro de Oracle Database o debajo de Oracle Database, en la red o en el sistema operativo?

NMON no responderá automáticamente todas esas preguntas, pero proporciona otra fuente temporal de evidencia.


Una característica silenciosa, pero importante

NMON probablemente no será una de las características que más atención reciba en Oracle AI Database 26ai.

No tiene la visibilidad comercial de Vector Search, SQL AI, Select AI o las nuevas capacidades relacionadas con inteligencia artificial.

Sin embargo, desde la perspectiva de administración y diagnóstico, resulta particularmente interesante.

Nuestra investigación demuestra que NMON:

  • mantiene estadísticas SYSTEM, IPIF y una infraestructura PER-FLOW;
  • posee consumidores internos asociados incluso con SQLNet y LREG;
  • monitoriza interfaces físicas y virtuales;
  • obtiene estadísticas del stack TCP/IP;
  • contempla estadísticas RDS;
  • trabaja con muestras de hasta cinco segundos en nuestra configuración;
  • mantiene tanto valores acumulados como diferencias entre muestras;
  • conserva información histórica;
  • y permite volcarla mediante DBMS_NETMON.DUMP_HISTORICAL_STATS.

El detalle más revelador quizá sea que Oracle denomine internamente a esa estructura:

KSNMON PRIVATE BUCKET

No estamos simplemente ante un nuevo proceso que verifica si una interfaz está activa.

Estamos ante una infraestructura de telemetría de red integrada dentro de Oracle Database.

Y probablemente apenas estamos comenzando a descubrir cuánto sabe NMON sobre lo que ocurre entre la base de datos y la red que la rodea.