Pregunta

En nuestra configuración de servidor / cliente estamos experimentando un comportamiento extraño. El cliente es una aplicación C / C ++ que utiliza OCI para conectarse a un servidor Oracle (utilizando la biblioteca OTL ) .

De vez en cuando el servidor DB muere de alguna manera (sí, este es el problema central, pero desde el lado de la aplicación no podemos resolverlo, pero tenemos que lidiar con él de todos modos), que la máquina ya no responde a nuevas solicitudes / conexiones, pero las existentes, como las conexiones de Oracle, no se caen ni caducan. Las consultas enviadas a la base de datos simplemente ya nunca regresan con éxito.

¿Qué posibilidades (si las hay) ofrece Oracle para detectar estas conexiones estancadas desde el lado de la aplicación cliente y recuperar de una manera más o menos segura?

¿Fue útil?

Solución

Este es un error en Oracle (o llamarlo una característica) hasta 11.1.0.6 y dijeron que el parche en Oracle 11g versión 1 (parche 11.1.0.7) que tiene la solución. Necesito ver eso. Si sucede, tendrá que cancelar (matar) el hilo que realiza esta acción. Sin embargo, no es un buen enfoque

Otros consejos

En todo mi esquema de DB tengo una tabla con un registro constante. Solo sondee periódicamente dicha tabla mediante una simple solicitud de SQL. Todos los demás métodos no son confiables.

Hay una API set_timeout en OTL que podría ser útil para esto.

Editar: en realidad, ignora eso. set_timeout no funciona con OCI. Eche un vistazo a la descripción de set_timeout de aquí donde describe un técnica que se puede usar con OCI

Parece que necesita disparar una consulta a la base de datos (por ejemplo, SELECT * FROM dual; ), luego, si la base de datos no ha respondido dentro de un período de tiempo especificado, suponga que el servidor ha murió y reaccionó en consecuencia. Me temo que no conozco C / C ++, pero ¿puede usar subprocesos múltiples para activar la declaración y luego esperar la respuesta, sin colgar la aplicación?

Esto funciona: he hecho exactamente lo que estás buscando. Haga que un proceso padre (A) cree un proceso hijo (B). El proceso hijo (B) se conecta a la base de datos, realiza una consulta (algo así como " seleccione 1 de una_tabla " obtendrá un mejor rendimiento si evita usar " dual " para esto y crea su propia tabla). Si (B) tiene éxito, escribe que fue exitoso y sale. (A) está esperando una cantidad de tiempo específica. Usé 15 segundos. Si (A) detecta que (B) todavía se está ejecutando, entonces puede suponer que la base de datos está bloqueada, mata (B) y toma las medidas necesarias (como llamarme por teléfono con un SMS).

Si configura SQL * NET para usar un tiempo de espera, probablemente notará que las consultas grandes fallarán debido a ello. La configuración OCI set_timeout también causará esto.

Hay una forma manual de evitar esto. Puede abrir un firewall y hacer algo como hacer ping en la base de datos después de cada período de tiempo especificado. De esta manera, la conexión de la base de datos no se perderá.

idea

If (current_time - lastPingTime > configuredPingTime)
{
     //Dummy query
     select 1 from dual;
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top