ORA-12516: TNS listener could not find available handler
El error que corona todas las guerras de conexiones: qué significa exactamente que el listener no encuentre un handler y cómo se resuelve processes, sessions y pools.
De todos los errores de conexión de Oracle, el ORA-12516 es el que llega con peor fama, porque no aparece al principio sino en el peor momento: la aplicación lleva días funcionando y de pronto nadie puede conectarse. El texto completo —TNS:listener could not find available handler with matching protocol stack— despista, porque sugiere un problema de red. Casi nunca lo es: el listener está sano; lo que no hay son handlers, procesos servidor disponibles a los que entregar la conexión.
Qué es un handler y por qué se agotan
Cuando un cliente llama, el listener recibe la petición y la deriva a un proceso servidor dedicado (o a un dispatcher, en configuración compartida). Cada proceso servidor consume una ranura de los parámetros de inicialización PROCESSES y SESSIONS. Cuando todas las ranuras están ocupadas, el listener no tiene a quién entregar la conexión y responde con el ORA-12516. La pregunta correcta no es «qué le pasa al listener» sino «quién se está comiendo los procesos».
-- cuanta ranura hay y cuanta se usa
SELECT resource_name, current_utilization,
max_utilization, limit_value
FROM v$resource_limit
WHERE resource_name IN ('processes', 'sessions');
SHOW PARAMETER processesSi CURRENT_UTILIZATION está pegado a LIMIT_VALUE, el diagnóstico está hecho. MAX_UTILIZATION cuenta el pico histórico desde el arranque: un valor rozando el límite anticipará la próxima caída aunque ahora mismo se haya liberado.
Quién consume: las sesiones inactivas
SELECT username, machine, program, status,
COUNT(*) AS sesiones,
ROUND(AVG(last_call_et)/60) AS min_inactivo
FROM v$session
WHERE username IS NOT NULL
GROUP BY username, machine, program, status
ORDER BY sesiones DESC
FETCH FIRST 12 ROWS ONLY;El patrón habitual: decenas de sesiones INACTIVE desde la misma máquina y el mismo programa, con minutos u horas de LAST_CALL_ET. Esa firma es una aplicación que abre conexiones y no las cierra, o un pool dimensionado con optimismo —cientos de conexiones para una carga que necesitaría diez. Cada conexión JDBC física es un proceso del servidor: mantenerlas ociosas «por si acaso» quema ranuras que otros necesitan.
Subir el límite: cirugía con spfile
ALTER SYSTEM SET processes=400 SCOPE=SPFILE;
ALTER SYSTEM SET sessions=448 SCOPE=SPFILE;
-- ojo: requiere reinicio para aplicarse
SELECT COUNT(*) FROM v$process; -- proceso actualPROCESSES es estático: el SCOPE=SPFILE lo deja escrito para el siguiente arranque, así que la operación conlleva ventana de reinicio. La regla de cálculo tradicional apunta SESSIONS = (1.1 × PROCESSES) + 5, aunque en versiones modernas se deriva solo si no se fija. Subir el límite es legítimo —el servidor crece, los procesos por lotes de Data Pump también consumen ranuras—, pero conviene hacerlo después de la auditoría de sesiones: duplicar PROCESSES sin cerrar la fuga solo compra tiempo hasta el mismo error con más memoria gastada.
La prevención está en el cliente
- Pools pequeños: HikariCP con
maximumPoolSizecontenido; el artículo de conexión JDBC con Oracle lo detalla. La fórmula sana: pocas conexiones muy usadas, no muchas conexiones dormidas. - Perfil de sesión:
ALTER PROFILE default IDLE_TIME 30;mata sesiones dormidas más allá del cuarto de hora, con la cooperating del proceso de fondo. - Timeout del listener: en configuraciones compartidas, revisar
DISPATCHERSy el registro del listener conlsnrctl servicesconfirma cuántos handlers están bloqueados frente a disponibles.
Parientes cercanos
El ORA-12520 es su hermano pequeño (handler temporalmente no disponible, típico en picos de conexiones simultáneas) y el ORA-00020 es el mismo agotamiento visto desde dentro: la sesión ya conectada que intenta crear un proceso hijo y encuentra el contador a tope. Los tres comparten diagnóstico y cura. El orden de comprobación que ha funcionado una y otra vez: v$resource_limit, luego v$session agrupada por programa, y solo al final el reinicio con parámetros nuevos.
El listener es el recepcionista, no el hotel. Si el hotel está lleno, cambiar de recepcionista no acomoda a nadie.
Para montar la sesión de diagnóstico conviene tener SQL*Plus bien configurado, y para dimensionar cargas que luego moverás entre entornos, las consultas al diccionario completan el kit.