Skip to main content

Command Palette

Search for a command to run...

El lado oscuro del DRM en Oracle RAC: Micro-cortes y el evento 'gcs drm freeze'

Published
10 min read
El lado oscuro del DRM en Oracle RAC: Micro-cortes y el evento 'gcs drm freeze'

En un entorno Oracle RAC, la "magia" de la coherencia de caché tiene un precio.

Hoy analizaré un caso real (los que me gustan!) donde el mecanismo de Dynamic Remastering (DRM) causó un micro-delay de casi un segundo, demorando transacciones críticas.

El síntoma: El evento de espera "fantasma"

Al revisar la ASH (dba_hist_active_sess_history) debido a una demora puntual de menos de 1 segundo, detecto algo que me llama la atención.

SYS@cdbxxx1> SELECT
    event,
    count(*) as total_capturas,
    round(avg(wait_time+time_waited)/1000, 2) as avg_wait_ms
FROM dba_hist_active_sess_history
WHERE sample_time BETWEEN TO_TIMESTAMP('22/02/26 06:13:00', 'DD/MM/YY HH24:MI:SS')
                      AND TO_TIMESTAMP('22/02/26 06:14:00', 'DD/MM/YY HH24:MI:SS')
GROUP BY event
ORDER BY 3 DESC;


EVENT								 TOTAL_CAPTURAS AVG_WAIT_MS
---------------------------------------------------------------- -------------- -----------
gcs drm freeze in enter server mode					      1      919.47
LGWR worker group ordering						      1       33.48
log file sync								     31       26.52
LGWR any worker group							      2       17.67
									      4 	.75
db file sequential read 						      1 	 .7
buffer busy waits							      1 	.39
log file parallel write 						      2 	.38
rdbms ipc reply 							      1 	  0


Evento: gcs drm freeze in enter server mode

Tiempo de espera: 919.47 ms (¡Casi 1 segundo!)

¿Qué estaba pasando internamente? (La traza de LMON)

La traza del proceso LMON nos da la respuesta. El sistema detectó que ciertos objetos tenían una carga de lectura/escritura que no era óptima para su ubicación actual y decidió "remasterizarlos" (mover la gestión del objeto de un nodo a otro).

*** 2026-02-22T06:13:24.101236+01:00 (CDB$ROOT(1))

* DRM RCFG called (swin 0)
* kjfcdrmrfg: cap sync timeout at 3 * default (752 -> 489 secs, res limit 7518552)
Begin DRM(29029) (swin 0)
 AFFINITY pdb 3 tsn 13 object id 720963, * -> 2 obj size:7333
 AFFINITY pdb 3 tsn 12 object id 720969, 1 -> * obj size:449893
 AFFINITY pdb 3 tsn 11 object id 720996, 1 -> * obj size:217838
 AFFINITY pdb 3 tsn 52 object id 731023, * -> 2 obj size:92115
 AFFINITY pdb 3 tsn 13 object id 731026, * -> 2 obj size:6331
 AFFINITY pdb 3 tsn 13 object id 731027, * -> 2 obj size:12668
 AFFINITY pdb 3 tsn 13 object id 731028, * -> 2 obj size:5780
 AFFINITY pdb 3 tsn 13 object id 731029, * -> 2 obj size:6685
 AFFINITY pdb 3 tsn 13 object id 731030, * -> 2 obj size:6077
 AFFINITY pdb 3 tsn 13 object id 731031, * -> 2 obj size:5386
 AFFINITY pdb 3 tsn 13 object id 731032, * -> 2 obj size:7677
 AFFINITY pdb 3 tsn 13 object id 731033, * -> 2 obj size:5352
 AFFINITY pdb 3 tsn 13 object id 731034, * -> 2 obj size:3425
 AFFINITY pdb 3 tsn 13 object id 731035, * -> 2 obj size:4113
 AFFINITY pdb 3 tsn 13 object id 731036, * -> 2 obj size:3602
 AFFINITY pdb 3 tsn 13 object id 731037, * -> 2 obj size:7983
 AFFINITY pdb 3 tsn 13 object id 731038, * -> 2 obj size:5376
 AFFINITY pdb 3 tsn 13 object id 731039, * -> 2 obj size:3714
 AFFINITY pdb 3 tsn 14 object id 329632, * -> 2 obj size:295
 AFFINITY pdb 3 tsn 13 object id 731040, * -> 2 obj size:5576
 AFFINITY pdb 3 tsn 13 object id 731041, * -> 2 obj size:7776
 AFFINITY pdb 3 tsn 13 object id 731042, * -> 2 obj size:2757
 AFFINITY pdb 3 tsn 13 object id 706860, 1 -> * obj size:131057
 AFFINITY pdb 3 tsn 13 object id 690745, * -> 2 obj size:634
 AFFINITY pdb 3 tsn 51 object id 733055, * -> 2 obj size:4095
 AFFINITY pdb 3 tsn 14 object id 447506, * -> 2 obj size:257
 AFFINITY pdb 3 tsn 13 object id 718971, * -> 2 obj size:1709
Max cumultv sz 2624716 sz limit  4294967295 pk cnt 27 total objsz 1005504
 individual max sizes [ 1005504 2624716 ]
 Estimated time 6.2 secs  (avgtime 0.9 secs, avgsize 384055)
* drm freeze
 drm (29029) freeze step (window 1) - posted lmses/lmds for mtobe
 drm (29029) freeze step (window 1) - apifrz = true
 drm (29029) freeze step (window 1) - all lms procs frozen
* drm sync 1
* drm cleanup
* kjfclmsync: lmses complete parallel work in step 0.33.0
* drm sync 2
* drm replay
* kjfclmsync: lmses complete parallel work in step 0.35.0
send ftd(35) to 2:
* drm sync 3
* drm fix writes
* kjfclmsync: lmses complete parallel work in step 0.37.0
* drm sync 4
* drm end
* window 1 time 0.9 secs)

* DRM RCFG called (swin 0)
* kjfcdrmrfg: cap sync timeout at 3 * default (768 -> 489 secs, res limit 7673832)
* drm freeze
 drm (29029) freeze step (window 2) - posted lmses/lmds for mtobe
 drm (29029) freeze step (window 2) - apifrz = true
 drm (29029) freeze step (window 2) - all lms procs frozen
* drm sync 1
* drm cleanup

*** 2026-02-22T06:13:25.234977+01:00 (CDB$ROOT(1))
* kjfclmsync: lmses complete parallel work in step 0.33.0
* drm sync 2
* drm replay
* kjfclmsync: lmses complete parallel work in step 0.35.0
send ftd(35) to 2:
* drm sync 3
* drm fix writes
* kjfclmsync: lmses complete parallel work in step 0.37.0
* drm sync 4
* drm end
* window 2 time 1.0 secs)

window 1 time 0.9 secs: Exactamente los 919 ms que capturó el ASH

El momento del "Freeze"

Lo más crítico de la traza es cuando Oracle congela los procesos LMS (los encargados de mover los bloques de datos por el interconnect):

* drm freeze drm (29029) freeze step (window 1)
* apifrz = true 
* all lms procs frozen

¿Por qué es esto un problema? Cuando los procesos LMS se congelan para reorganizar las afinidades de los objetos, toda la comunicación de bloques entre nodos se detiene. Si tu aplicación está intentando leer un dato que está en el otro nodo en ese instante, la sesión se queda colgada en el evento gcs drm freeze.

Los objetos afectados: Identificando a los culpables

Cruzando los datos de gv$policy_history y dba_objects, veo que el sistema estuvo moviendo afinidades de particiones críticas:

select h.*,o.object_name, o.SUBOBJECT_NAME 
from gv$Policy_History h, dba_objects o
where h.data_object_id = o.data_object_id 
and o.object_id IN (564682, 391009, 504609, 626248, 716966, 720969, 720996) 
and  TO_DATE(EVENT_DATE, 'MM/DD/YYYY HH24:MI:SS') BETWEEN TO_DATE('02/22/2026 06:00:00', 'MM/DD/YYYY HH24:MI:SS') AND TO_DATE('02/22/2026 07:00:00', 'MM/DD/YYYY HH24:MI:SS')
order by TO_DATE(EVENT_DATE, 'MM/DD/YYYY HH24:MI:SS') desc;

   INST_ID POLICY_EVENT           DATABASE_ID TABLESPACE_ID DATA_OBJECT_ID TARGET_INSTANCE_NUMBER EVENT_DATE               CON_ID OBJECT_NAME                                                                                                                      SUBOBJECT_NAME                                                                                                                  
---------- ---------------------- ----------- ------------- -------------- ---------------------- -------------------- ---------- -------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------
         1 initiate_affinity                3            12         720969                      2 02/22/2026 06:15:37           0 TABLA1                                                                                                                    SYS_P16222                                                                                                                      
         1 initiate_affinity                3            51         716966                      2 02/22/2026 06:15:37           0 TABLA2                                                                                                                     SYS_P16177                                                                                                                      
         1 initiate_affinity                3            11         720996                      2 02/22/2026 06:15:37           0 TABLA3                                                                                                        SYS_P16226                                                                                                                      
         1 push_affinity                    3            14         564682                      2 02/22/2026 06:05:37           0 TABLA4                                                                                                                        SYS_P15690                                                                                                                      
         1 push_affinity                    3            14         504609                      2 02/22/2026 06:05:37           0 TABLA4                                                                                                                        SYS_P15471                                                                                                                      
         1 push_affinity                    3            14         391009                      2 02/22/2026 06:05:37           0 TABLA4                                                                                                                        SYS_P15123                                                                                                                      
         1 push_affinity                    3            14         626248                      2 02/22/2026 06:05:37           0 TABLA4                                                                                                                        SYS_P15914                                                                                                                      

El sistema "empujó" (push_affinity) la gestión de los objetos hacia la instancia 2.

El "Culpable" Inesperado: El Job de Estadísticas

En nuestro caso real, tras investigar los horarios y el module de las sesiones, descubrimos al responsable. No era un error de la aplicación, sino el Job automático de estadísticas que entró por el nodo 2. La tormenta perfecta

  • La Aplicación está trabajando intensamente en el Nodo 1, leyendo y escribiendo. Oracle ha establecido la afinidad de esos objetos en el Nodo 2 para optimizar el rendimiento.

  • El Job de Estadísticas se lanza desde el Nodo 2. Para calcular las estadísticas, el Nodo 12empieza a pedir masivamente bloques .

  • El Conflicto: El DRM de Oracle ve que el Nodo 2 ahora tiene una actividad brutal sobre esos objetos. Consulta su parámetro gcaffinity_ratio y dice: "Oye, el Nodo 2 está pidiendo esto mucho más que antes, voy a mover la maestría del objeto del Nodo 1 al Nodo 2".

  • El Resultado: Durante ese cambio de "dueño", se produce el GCS Freeze. La aplicación en el Nodo 1 se detiene en seco durante 919 ms esperando a que el Nodo 2 termine de reclamar la propiedad de los datos.

El "Secuestro" de la Afinidad

Lo que ocurrió en este caso es un secuestro de afinidad. Las estadísticas engañaron al DRM haciéndole creer que el nodo donde se ejecutaban era el más importante. El freeze de 919 ms fue el precio que pagó la aplicación mientras Oracle le "quitaba" las llaves de la tabla para dárselas al proceso de estadísticas.

Opciones de Ajuste Fino (Tuning) del DRM

Si decides mantener el DRM activo para aprovechar la optimización del Interconnect, pero quieres evitar los freezes causados por procesos como las estadísticas, tienes estos tres niveles de configuración:

El "Filtro de Ruido" (_gc_affinity_ratio)

Este es el parámetro que determina cuánta "presión" debe ejercer un nodo remoto para robarle la maestría a otro.

Valor por defecto: 50.

Ajuste recomendado: 1000 o superior.

Efecto: Al subirlo a 1000, el proceso de estadísticas tendría que realizar muchísimas más solicitudes que la aplicación para que el DRM considere que vale la pena mover el objeto. Esto hace que el sistema ignore "picos" de trabajo de mantenimiento y se mantenga fiel a la aplicación OLTP.

La "Ventana de Paciencia" (_gc_policy_time)

Controla cada cuánto tiempo (en minutos) Oracle evalúa si debe remasterizar objetos.

Valor por defecto: 10.

Ajuste recomendado: 60.

Efecto: Si tu job de estadísticas dura 30 minutos, pero la ventana de evaluación es de 60, el job terminará antes de que el DRM decida que el cambio de maestría es necesario. Evitas el freeze simplemente siendo más paciente.

El "Límite de Agresión" (_gc_affinity_limit)

Define el número mínimo de accesos necesarios para que un objeto sea siquiera candidato a DRM.

Ajuste recomendado: Incrementar el valor actual (puedes ver el actual en V$GC_POLICY_MODIFICATIONS).

Efecto: Evita que tablas pequeñas o medianas sean movidas de nodo constantemente por consultas aleatorias o jobs rápidos, reservando el DRM solo para objetos donde el ahorro de tráfico sea masivo y justificado.

Segmentación y Afinidad de Servicios

Si tu entorno tiene múltiples aplicaciones, la solución no es solo mover las estadísticas, sino separar las cargas de trabajo por nodos. De esta forma, el DRM deja de ser un problema para convertirse en un aliado silencioso.

Segmentación de Aplicaciones

Imagina que tienes la App A y la App B. Si ambas conectan a ambos nodos, el Interconnect será un caos de tráfico cruzado.

Nodo 1: Configurado como PREFERRED para el servicio de la App A.

Nodo 2: Configurado como PREFERRED para el servicio de la App B.

El lugar de las Estadísticas en un entorno segmentado

En este escenario, tienes dos opciones inteligentes para el mantenimiento:

  • Alineación Total: Lanzas las estadísticas de las tablas de la App A en el Nodo 1, y las de la App B en el Nodo 2 Resultado: El DRM no se inmuta. Los bloques ya están donde deben estar. Es la opción más eficiente en red.

  • Nodo de Mantenimiento Dedicado: Si prefieres no cargar los nodos donde están las Apps, puedes usar un tercer nodo (si lo tienes) o un nodo con menos carga. Pero aquí debes usar el tuning de parámetros (_gc_affinity_ratio) para que el DRM no intente "robar" la maestría de las tablas hacia el nodo de mantenimiento.

Conclusión

El DRM es una herramienta de optimización, pero es ciega. No sabe qué proceso es más importante; solo ve volumen de tráfico. Si dejas que las estadísticas corran en el nodo donde menos impacto tendrá, el DRM castigará a tu aplicación para favorecer a un proceso de mantenimiento.

More from this blog

Carla Muñoz López

64 posts

Soy DBA senior de bases de datos Oracle y me defino como una persona alegre y creativa. Apasionada por conocer, compartir ideas, divertirme y seguir aprendiendo todo lo relacionado con Oracle.