# Cursor Sharing y Binds Grandes: Cómo Diagnosticamos y Solucionamos un Caso Real con el Evento 10503 en Oracle

En entornos Oracle de alto rendimiento, la aparición de múltiples child cursors debido a BIND\_MISMATCH es un problema común que puede degradar el rendimiento significativamente.

Nuestra aplicación, que utiliza extended strings, comenzó a presentar una elevada cantidad de child cursors en dos sentencias INSERT críticas.

**La Investigación y el Diagnóstico**

El primer paso fue identificar el origen exacto del BIND\_MISMATCH. Para ello, seguimos un proceso meticuloso:

Identificación de los SQL\_ID problemáticos: A través de V$SQL y V$SQL\_SHARED\_CURSOR, localizamos los dos SQL\_ID involucrados (xxxxxxxxxxxxx1 y xxxxxxxxxxxxx2).

Para encontrar el motivo de un cursor no compartido:

```plaintext
-- Script Code
set serveroutput on

DECLARE
  v_count number;
  v_sql varchar2(500);
  v_sql_id varchar2(30) := '&sql_id';
BEGIN
  v_sql_id := lower(v_sql_id);
  dbms_output.put_line(chr(13)||chr(10));
  dbms_output.put_line('sql_id: '||v_sql_id);
  dbms_output.put_line('------------------------');
  FOR c1 in
    (select column_name 
       from dba_tab_columns
      where table_name ='V_$SQL_SHARED_CURSOR'
        and column_name not in ('SQL_ID', 'ADDRESS', 'CHILD_ADDRESS', 'CHILD_NUMBER', 'REASON', 'CON_ID')
      order by column_id)
  LOOP
    v_sql := 'select count(*) from V_$SQL_SHARED_CURSOR
              where sql_id='||''''||v_sql_id||''''||'
              and '||c1.column_name||'='||''''||'Y'||'''';
    execute immediate v_sql into v_count;
    IF v_count > 0
    THEN
      dbms_output.put_line(' - '||rpad(c1.column_name,30)||' count: '||v_count);
    END IF;
  END LOOP;
END;

Versions Summary
----------------
BIND_MISMATCH :121 <<<<<<<<<<-----------------
ROLL_INVALID_MISMATCH :2
BIND_LENGTH_UPGRADEABLE :9
```

Análisis de los binds: La clave fue consultar la vista V$SQL\_BIND\_CAPTURE para entender la variabilidad en el tamaño de los binds para cada una de las sentencias.

Para el primer SQL\_ID: sql

```plaintext
SELECT COUNT(*) AS count,
       position,
       MIN(max_length) AS min_length,
       MAX(max_length) AS max_length,
       datatype,
       CASE 
         WHEN MAX(value_string) IS NOT NULL THEN 'Yes' 
         ELSE 'No' 
       END AS bind_captured,
       '('||MAX(precision)||','||MAX(scale)||')' AS graduation
  FROM gv$sql_bind_capture
  WHERE  sql_id = 'xxxxxxxxxxxxx1'
 GROUP BY position, datatype
 ORDER BY max_length desc;

COUNT(*) POSITION MIN(MAX_LENGTH) MAX(MAX_LENGTH) DATATYPE BIND GRADUATION (PRECISION,SCALE)
======== ======== =============== =============== ======== =============== =================
21 1 22 22 2 No (,)
21 2 32 32 1 No (,)
21 3 2000 2000 1 No (,)
21 4 2000 2000 1 No (,)
21 5 2000 2000 1 No (,)
21 6 7 7 12 No (,)
21 7 22 22 2 No (,)
12 8 2000 2000 1 No (,)
9 8 22 22 2 No (,)
21 9 32 2000 1 Yes (,)
21 10 128 128 1 No (,)
21 11 128 128 1 No (,)
21 12 22 22 2 No (,)
21 13 2000 2000 1 No (,)
21 14 2000 2000 1 No (,)
21 15 32 2000 1 Yes (,)
21 16 2000 2000 1 No (,)
21 17 128 2000 1 Yes (,)
```

Los resultados mostraron que los binds de tipo VARCHAR2 en varias posiciones variaban entre 32 y 2000 bytes. ¡Este era el culpable del BIND\_MISMATCH para la primera INSERT.

> High Version Count Due To BIND\_MISMATCH ( [Doc ID 336268.1](https://support.oracle.com/epmos/faces/DocumentDisplay?parent=SrDetailText&sourceId=3-40676398581&id=336268.1) [)](https://support.oracle.com/epmos/faces/DocumentDisplay?parent=SrDetailText&sourceId=3-40676398581&id=336268.1)

[Aplicación](https://support.oracle.com/epmos/faces/DocumentDisplay?parent=SrDetailText&sourceId=3-40676398581&id=336268.1) de la solución: Basándonos en este análisis, aplicamos el evento 10503 con el nivel específico que necesitábamos:

```plaintext
ALTER SYSTEM SET EVENTS '10503 trace name context forever, level 2000';
```

Resultado: El problema de los child cursors para la primera sentencia INSERT se resolvió por completo.

El segundo problema: Tras el primer éxito, nos enfocamos en el segundo SQL\_ID (xxxxxxxxxxxxx2). Repetimos el análisis y descubrimos que sus binds llegaban hasta 16,386 bytes.

Aplicamos el evento con un nivel superior:

```plaintext
ALTER SYSTEM SET EVENTS '10503 trace name context forever, level 16386';
```

**La Limitación**

Para nuestra sorpresa, el segundo problema no se resolvió. Al contactar con Soporte de Oracle, confirmaron nuestra sospecha: **el evento 10503 tiene una limitación interna y no funciona para binds mayores a 4000 bytes**, incluso si se establece un nivel superior.

**Conclusión y Lecciones Aprendidas**

El diagnóstico es clave: La solución no es aplicar el evento 10503 a ciegas. La consulta a V$SQL\_BIND\_CAPTURE para obtener el MAX(MAX\_LENGTH) de los binds problemáticos es un paso fundamental y no negociable para determinar el nivel correcto.

Solución para binds &lt;= 4000 bytes: Para la primera INSERT, el evento 10503 configurado al nivel preciso (2000) fue la solución perfecta y eliminó el BIND\_MISMATCH.

Limitación actual para binds &gt; 4000 bytes: Para la segunda INSERT, chocamos con un muro. Oracle confirmó que no hay solución nativa actualmente y que no hay planes a corto plazo para extender el evento más allá de 4000 bytes.

**Reflexión Final**

Este caso es un ejemplo perfecto de cómo un enfoque metódico—identificar, diagnosticar y aplicar—nos permitió resolver el 50% del problema. Para el otro 50%, nos topamos con una limitación actual de la base de datos.

**Cambio persistente en spfile**

Para que el cambio aplique tras reinicios

```plaintext
ALTER SYSTEM SET EVENT= '10503 trace name context forever, level 2000'  COMMENT='High Version Count Due To BIND_MISMATCH' SCOPE=SPFILE SID='*';
```
