Observaciones de contencion de row cache en un DWH y RAC

Recientemente he estado trabajando en un Data Warehouse de cargas en tiempo real que sufre bastantes problemas de cuelgues y caidas de sistema a causa de las contenciones de row cache.

Es un cluster de 6 nodos en 10.2.0.4 sin ningu PSU y suma aproximadamente 14TB de datos. Los jobs de ETL estan “modularizados” mediante servicios de base de datos. Uno de los nodos mas potentes tiene bastantes problemas cuando se inicializa la carga de todos los procesos de ETL de un modulo. Normalmente el sistema funciona bien con un 70% de ETL de este modulo.

Despues de muchas vueltas, investigaciones, troubleshooting, ver caidas en el tiempo real. Se observa que los cuelgues se provocan por una contencion masiva de row cache. Para tener una idea un Oracle E-Business Suite 11.5.10.2 con modulos de financials en uso normalmente tiene aproximadamente 15000 entradas en v$rowcache, una aplicacion “gorda” con 900 tablas podria llegar a unas 11000 entradas. En este DWH lo mas bajo son unas 500000 entradas en v$rowcache y 4500000 en el nodo que sufre problemas de cuelgue.
El problema surge cuando se llena un shared pool de 7GB a partir de ese momento el proceso lck (que gestiona recursos de row cache y library cache y en RAC se encarga de liberar memoria de shared pool) empieza a liberar memoria, por algun bug, creo que es 8666117, llegamos a esta situacion:

1. LCK liberando memoria y se observa el evento latch: row cache objects en su sesion, observo como bajan las entradas en v$rowcache y subre free memory en v$sgastat de shared pool
2. Las sesions que necesitan recursos de shared pool esperan por library cache lock, latch: row cache objects, latch: shared pool, row cache lock, enqeue CF
3. El sistema se queda literalmente “congelada” mientras LCK realiza su trabajo. Si la concurrencia es elevada y LCK no da a basto liberando memoria el sistema puede llegar a colapsarse y posteriormente caida por varias razones como la espera de enqueue CF (ORA-00494: enqueue [CF] held for too long), WAITED TOO LONG FOR A ROW CACHE ENQUEUE LOCK, en ocasiones se pierde la comunicaciones con ASM etc. Que es lo que ha sufrido en muchas ocasiones.
4. Se observa la comparacion del numero de las entradas de dc_segments antes y despues de liberar la memoria baja drasticamente, por ejemplo de 1500000 a 400000. Esta comparacion es posible si el sistema no ha caido, no cae siempre a veces se queda colgado durante 15 a 30 minutos y se recupera, es probable que los eventos de espera en estas ocasiones no son susceptibles a provocar caidas por un timeout como ORA-00494.

El workaround de momento es subir el shared pool a 12GB y el sistema consigue estabilizarse. Tambien he podido observar pero no contrastar que LCK en situaciones donde la actividad de shared pool es muy elevada intenta liberar la memoria de hasta que llegue un 35% libre y empieza a liberar cuando queda entre un 10% y 15% de memoria libre.

Este sistema esta compuesto por aproximadamente 24000 particiones de tablas, 200000 subparticiones de tablas, 200000 particiones de indices y 1800000 subparticiones de indices. Genera de media 20MB de redo por segundo, 4000000 de consistent gets por segundo, 150000 de physical reads por segundo, 10000 de physical writes por segundo y 10000 IOPS. A nivel de hardware un total de 108 procesadores y 208GB de memoria. Con una SGA total de 148GB.

3 thoughts on “Observaciones de contencion de row cache en un DWH y RAC

  1. carlosal

    Supongo que te refieres a ‘row cache locks’. Estos pueden venir de DDL’s (creación o recompilación de objetos durante las cargas -¿tablas temporales quzás?), pero también de gestión del espacio (extents y tablespaces reclaman también actividad en el ‘data dictionary’. Subir el ‘shared pool’ es un ‘workaround’. Identificar la causa final (objetos, espacio, ambos) sería importante aquí.

    Pero para solucionar todos tus problemas la solución es migrar a Teradata (‘shared nothing rules for DW!)😉

    Saludos.

    Carlos.

    Reply
  2. lscheng Post author

    Hola

    Constantemente se realiza truncate sobre las tablas temporales (no particionadas si no esto seria mucho peor), al ser un DWH de cuasi tiempo real los truncates son constantes (cada minuto entran cargas de millones de registros) asi que evitar TRUNCATE esta fuera de la question. Otra causa de la contention de row cache es insert a subparticiones, si se utiliza el append las peticiones a dc_users, dc_objects y dc_object_ids es bastante elevada se reduciria sin el append el cual no es una opcion en un DWH. Otra opcion de reducir es especificar insert append table partition() pero esta descartado por el momento porque hay que modificar bastante el codigo.

    En cuanto a las operaciones de gestion de espacio no parece ser problematico ya que se esta cargando sobre extensiones de tamaño de 32M y cada carga van a 8 subparticiones con parallel de 8. Cada subparticion suele terminar con un tamaño de entre 500MB y 1000MB.

    Cada vez que se hace un insert sobre una tabla con 800 subparticiones todos estos metadatos y de los objetos dependientes (subparticiones de todos los indices) se sube al row cache (y tardan un buen rato y durante esta subida a rowcache se observa el evento row cache lock). En circunstancias normales, es decir cuando hay memoria libre esto no penaliza al sistema como para provocar caidas ni penalizar el rendimiento sin embargo cuando el shared pool esta bajo presion y hay que liberar memoria y mientras tanto siguen entran peticiones de 800_POR_numero_de_indices_MAS_800_de_tabla el proceso LCK no libera la memoria lo suficientemente rapido, ahi es cuando vemos los cuelgues. Esto es peor en RAC porque si una sesion que esta bloqueado por LCK y esta sesion a su vez bloquea a otras sesiones de otros nodos por library cache lock y row cache lock a final podemos ver cuelgues en mas de un nodo.

    En resumen los cuelgues surgen cuando esta bajo presion el shared pool y creo que es provocado el bug sin embargo estoy seguro que si no es por el bug el rendimiento no seria muy optimo si el shared pool no es lo suficientemente grande para albergar todos los metadatos ya que no seria necesario subir al rowcache constantemente los metadatos de miles de subparticiones.

    Finalmente el fix de dc_tablespace_quotas se aplicó ya hace bastante tiempo, realmente no causaba tantos problemas. Las contenciones estan cocentrados en dc_segments, dc_objects, dc_object_ids y dc_users pero lo dicho si estan todos cacheados no hay problema de performance ni de cuelgues, el problema es cuando se queda sin memoria libre y el que tiene que liberar no lo hace con suficiente agilidad que deberia.

    Reply

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s