Saltar al contenido
WaitScope Entrar Solicitar acceso (por correo) Menú

Contención por estructuras internas de la base de datos

El hallazgo CONCORRENCIA aparece cuando latches, mutexes y buffer busy pesan en el tiempo total: cómo relacionar cada evento con su causa y corregirlo.

Se aplica a: Traces 10046 con esperas (nivel 8 o 12)

Los latches, mutexes y buffers protegen estructuras de la memoria de la base de datos: mientras una sesión trabaja en una de ellas, las otras que la necesitan esperan su turno. La causa suele ser parse en exceso, un bloque caliente o un objeto modificado mientras está en uso.

Síntomas

En el Diagnóstico aparece el hallazgo Contención por estructuras internas de la base de datos (CONCORRENCIA). El texto dice cuánto del tiempo total quedó en la clase de espera Concurrency, en porcentaje y en segundos, lista los eventos de la clase que pesaron y termina con Ver perfil por clase.

El hallazgo aparece cuando la clase Concurrency pesa en el tiempo total. La gravedad es media y pasa a alta cuando la clase pesa más. Entran en esta clase estos eventos, por la wait_class de Oracle 19c:

Eventos de la clase Concurrency, por tipo de contención
ContenciónEventos
Bloquesbuffer busy waits, latch: cache buffers chains, enq: TX - index contention
Parse y cursoreslatch: shared pool, latch: library cache, library cache lock, library cache pin, library cache load lock, library cache: mutex X, cursor: pin S wait on X, cursor: pin S, cursor: pin X, cursor: mutex S, cursor: mutex X
Diccionariolatch: row cache objects, row cache lock, row cache mutex
Otroslatch: In memory undo latch, os thread startup

read by other session queda en User I/O y latch free en Other: no cuentan aquí. Un evento que el informe no clasifica aparece en el perfil como No clasificado.

Causa

La sesión del trace disputó una estructura con otras sesiones que se ejecutaban al mismo tiempo. El trace muestra solo la espera de esta sesión; quien la disputaba con ella queda fuera de él. Causas comunes, de la más a la menos frecuente:

  • Parse en exceso: SQL con literales en lugar de bind variables, o un cursor abierto y cerrado en cada ejecución. Pesa en los latches de la shared pool y de la library cache y en los mutexes de cursor.
  • Bloque caliente por lectura lógica: muchas sesiones leyendo los mismos bloques, en general por un plan que vuelve a leer los mismos bloques (latch: cache buffers chains).
  • Inserción concurrente en el mismo bloque: un índice con clave creciente (secuencia, fecha) que recibe inserciones de varias sesiones (buffer busy waits, enq: TX - index contention).
  • Secuencia sin caché o con caché pequeña (row cache lock).
  • DDL, compilación o recolección de estadísticas en un objeto en uso, y cursores invalidados con frecuencia (library cache lock, library cache pin, cursor: pin S wait on X).
  • Consulta en paralelo que inicia los procesos de ejecución paralela (os thread startup).

Solución

Empiece por el evento que el hallazgo lista primero. Los casos van del más al menos común.

Parse en exceso

Revise la fila PARSE en Tipos de llamada: Misses cerca de Cantidad significa hard parse en casi todo PARSE. Si el Diagnóstico también muestra uno de estos hallazgos, empiece por él:

Bloque caliente por lectura lógica

Con latch: cache buffers chains, reduzca las lecturas lógicas de las sentencias que esperaron. Busque esas sentencias en el grupo Concurrency de Sentencias principales por componente y por clase y, en el plan de cada una, la operación con LIO propio alto (operación que concentra el plan). El caso típico es un NESTED LOOPS que vuelve a leer los mismos bloques miles de veces.

Inserción concurrente en el mismo bloque

En Objetos con más tiempo de espera, busque el índice o la tabla de las esperas. Para un índice con clave creciente, las salidas habituales son el índice reverse key y el índice global particionado por hash:

alter index exemplo.pedido_pk rebuild reverse;
create index exemplo.pedido_data_ix on exemplo.pedido (data_pedido)
  global partition by hash (data_pedido) partitions 16;

El índice reverse key deja de servir para búsquedas por rango en la clave (between, >), y el índice particionado exige la opción Partitioning. Para una tabla con buffer busy waits en inserción, compruebe si el segmento está en un tablespace con gestión automática del espacio (ASSM).

Secuencia sin caché

Para row cache lock en sentencias que usan NEXTVAL, revise la caché de las secuencias del esquema y aumente la de las más usadas:

select sequence_owner, sequence_name, cache_size, order_flag
  from dba_sequences
 where sequence_owner = 'EXEMPLO'
 order by cache_size;
alter sequence exemplo.pedido_seq cache 1000;

Con o sin caché, una secuencia no garantiza números sin huecos: el rollback también salta números. La caché solo aumenta el hueco cuando la instancia cae o la secuencia sale de la shared pool.

Objeto modificado mientras está en uso

El DDL, la compilación de paquetes y la recolección de estadísticas invalidan los cursores que usan el objeto, y las sesiones se detienen para rehacer el parse. Lleve esas tareas fuera del horario de uso. Si la sentencia tiene demasiadas versiones del cursor, v$sql_shared_cursor indica el motivo de cada versión:

select sql_id, version_count, executions, parse_calls
  from v$sqlarea
 order by version_count desc
 fetch first 20 rows only;

Procesos de consulta en paralelo

os thread startup es el tiempo de iniciar procesos, en general los de ejecución paralela. Revise el grado de paralelismo de las sentencias que esperaron: en una sentencia corta y muy ejecutada, el paralelismo cuesta más de lo que gana.

Cómo confirmar

La contención depende de cuántas sesiones hacen lo mismo al mismo tiempo. Un trace tomado con la base de datos vacía no prueba la corrección: mida en el mismo horario y con la misma carga de la medición anterior.

  1. Aplique una corrección por vez.
  2. Active el trace de la misma operación con esperas (activar el trace con DBMS_MONITOR).
  3. Envíe el archivo nuevo y abra el informe.
  4. Compare la fila Concurrency en Por clase de espera y las filas de los eventos en el perfil.

Resultado: la clase Concurrency deja de pesar en el tiempo total y el hallazgo desaparece del Diagnóstico. Cuando la causa era el parse, la columna Misses de la fila PARSE en Tipos de llamada también baja.

En el informe

El informe de ejemplo no tiene esperas de la clase Concurrency; los enlaces abren las mismas secciones en él.

Actualizado el 29/10/2026. Informar un error en esta página