Domanda

Nella configurazione del nostro server / client stiamo riscontrando un comportamento strano. Il client è un'applicazione C / C ++ che utilizza OCI per connettersi a un server Oracle (utilizzando la libreria OTL ) .

Di tanto in tanto il server DB muore in un certo senso (sì, questo è il problema principale, ma dal lato dell'applicazione non siamo in grado di risolverlo ma dobbiamo comunque gestirlo), che la macchina non risponde più a nuove richieste / connessioni ma quelle esistenti, come Oracle-connessioni, non vengono interrotte o scadute. Le query inviate al DB non vengono più restituite correttamente.

Quali possibilità (eventuali) sono fornite da Oracle per rilevare queste connessioni bloccate dal lato dell'applicazione client e ripristinarle in modo più o meno sicuro?

È stato utile?

Soluzione

Questo è un bug in Oracle (o chiamalo una funzione) fino all'11.1.0.6 e hanno detto che la patch su Oracle 11g versione 1 (patch 11.1.0.7) ha la correzione. Devo vederlo. Se succede, dovrai annullare (uccidere) il thread che esegue questa azione. Non un buon approccio però

Altri suggerimenti

In tutto il mio schema DB ho una tabella con un record costante. Basta eseguire il polling periodico di tale tabella con una semplice richiesta SQL. Tutti gli altri metodi non affidabili.

C'è un'API set_timeout in OTL che potrebbe essere utile per questo.

Modifica: in realtà, ignoralo. set_timeout non funziona con OCI. Dai un'occhiata alla descrizione set_timeout da qui dove descrive un tecnica che può essere utilizzata con OCI

Sembra che tu debba lanciare una query nel database (ad es. SELECT * FROM dual; ), quindi se il database non ha risposto entro un determinato periodo di tempo, supponi che il server abbia è morto e reagire di conseguenza. Temo di non conoscere C / C ++, ma puoi usare il multi-threading per attivare la dichiarazione e attendere la risposta, senza sospendere l'applicazione?

Funziona così: ho fatto esattamente quello che stavi cercando. Chiedi a un processo padre (A) di creare un processo figlio (B). Il processo figlio (B) si collega al database, esegue una query (qualcosa come " seleziona 1 da a_table " - otterrai prestazioni migliori se eviti di usare " dual " per questo e crei la tua tabella). Se (B) ha esito positivo, indica che ha avuto successo ed esce. (A) è in attesa per un determinato periodo di tempo. Ho usato 15 secondi. Se (A) rileva che (B) è ancora in esecuzione - allora può presumere che il database sia bloccato - Uccide (B) e compie le azioni necessarie (come chiamarmi al telefono con un SMS).

Se si configura SQL * NET per utilizzare un timeout, si noterà probabilmente che query di grandi dimensioni non riusciranno a causa di esso. Anche la configurazione OCI set_timeout causerà questo.

C'è un modo manuale per evitarlo. Puoi aprire un firewall e fare qualcosa come il database ping dopo ogni periodo di tempo specificato. In questo modo la connessione al database non andrà persa.

idea

If (current_time - lastPingTime > configuredPingTime)
{
     //Dummy query
     select 1 from dual;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top