Evitar que un firewall nos fastidie las conexiones Oracle que tardan mucho en responder

Los que tengan en su data center bases de datos Oracle y no tengan permiso para cambiar la configuración de red seguramente habrán encontrado este problema alguna vez: las queries lanzadas desde un cliente hasta Oracle se desconectan cuando la query es pesada y tarda mucho rato en responder (lo normal es pasado 1h o 2h, aunque he visto casos de conexiones cortadas a los 5-10 minutos).

Esto es una situación poco frecuente pero posible: desde un cliente se lanza una query para un reporte inmenso (generalmente en un proceso batch) que, por falta de tuning o por lo que sea, tarda más de X rato. Y en ese X clavado se corta la conexión.

Algunas veces se pueden tocar los timeouts en el sqlnet.ora, pero en mi caso han sido las que menos. El problema que yo me encontré no está en la base de datos, sino en el firewall que había entre el cliente y el servidor Oracle. Dicho firewall (en mi caso fue un sonicwall, hace poco lo he visto con F5 y sé que pasa con otros muchos) está configurado para cortar las "idle connections" pasado un tiempo X. Como la base de datos está procesando y no devuelve nada hasta que acaba, el firewall interpreta que la conexión está inactiva y la corta.

Para evitar este problema, podemos o bien pedir a redes que hagan su trabajo y reconfiguren para que no corte estas conexiones (si son competentes no habrá problema) o hacerlo nosotros mismos. Pero, cuando esto no es una posibilidad, tenemos la opción de forzar al cliente para que mande paquetes keepalive.

Lo primero es configurar las opciones de keepalive en el kernel a nivel de /etc/sysctl.conf. Por ejemplo, podemos especificar esto en el archivo:

net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_intvl = 60
net.ipv4.tcp_keepalive_probes = 5

y aplicarlo con un sysctl -p

Ahora queda el paso final. Para que el cliente Oracle aplique estos keepalive y vaya mandando paquetes (y que, por tanto, el firewall no piense que la conexión está inactiva), debemos añadir esto a la cadena de conexión:

(enable=broken)

Añadiendo esto a la parte de DESCRIPTION del connection string, el firewall ya no cortará las sesiones.

Saludos!