2009-10-26 13 views
7

Abbiamo trovato un bug nel vecchio codice in cui le connessioni non vengono chiuse. È una soluzione semplice, ma mi chiedo come proveremo a correggere. È possibile scegliere di utilizzare un pool di connessioni o meno. Per il pooling, sarebbe facile aggiungere il monitoraggio per il pool, ma quando il pooling delle connessioni non viene utilizzato, come monitoriamo quelle connessioni non chiuse e orfane? È come qualsiasi altra perdita di memoria?Come si traccia le connessioni JDBC orfane che non sono chiuse?

Il bug sembra fondamentalmente un errore di copia e incolla. Abbiamo un paio di classi che gestiscono la connessione DB, in modo che appaia più o meno in questo modo:

OurDBConn conn1 = ConnectionManager.getConnection(); 
try { 
    // business logic 
} catch() { 
    // 
} finally { 
    ConnectionManager.returnConnection(conn1); 
} 

/// and then later in the same method 
OurDBConn conn2 = ConnectionManager.getConnection(); 
try { 
    // business logic 
} catch() { 
    // 
} finally { 
    ConnectionManager.returnConnection(conn1); // NOTE Error: conn1 should be conn2 
} 

Non so il motivo per cui i programmatori precedenti non solo riutilizzare la connessione originale, ma questo è quello che è

(inizio modifica/aggiungi)

Sì, anche il codice di connessione è nostro e quindi posso utilizzare le risposte fornite.

Tuttavia, non penso di aver posto la domanda giusta, sebbene le risposte seguenti rispondano alla domanda che ho posto. Non sono sicuro di quale sia la cosa giusta da fare sullo stackoverflow; fai un'altra domanda o modifica questa?

Una delle domande che avrei dovuto porre è: in che modo queste connessioni orfane e non chiuse si manifestano nelle prestazioni del sistema? Inoltre, poiché questi oggetti di connessione esistono solo nell'ambito di un determinato metodo, le connessioni non sarebbero idonee per la garbage collection? E poi se sono gc'ed, qual è l'effetto delle connessioni aperte che vengono fatte?

(fine edit)

+0

Lo osserverò da vicino, abbiamo un problema molto simile in molti dei nostri progetti. – Tenner

+1

Per la cronaca, dovrei avere una buona ragione per NON spostarlo in un'implementazione di pool di connessioni mature come DBCP o C3PO - se ne hai l'opportunità - forse dovresti considerare di farlo? – teabot

risposta

7

Supponendo che la gestione connessione è anche il proprio codice, è possibile memorizzare i collegamenti inizializzata (insieme a una stacktrace) in una mappa all'interno della gestione connessione, e poi rimuoverli quando sono restituiti . Quindi, in qualsiasi punto, il keyset della mappa è l'insieme di connessioni non restituite, e puoi cercare quel valore nella mappa per trovare il bit di codice colpevole che li ha creati e mai rilasciati. (Se la connessione non è una chiave di mappa adatta, è possibile utilizzare probabilmente una sorta di ID univoco o numero di connessione o qualsiasi altra cosa: il valore effettivo non ha importanza tanto quanto la sua presenza).

Quindi basta aggiungere un modo appropriato per accedere a questa mappa su richiesta e si sta bene. A seconda del proprio ambiente, l'aggiunta di un hook di chiusura che esegue il dump del contenuto della mappa su un file e/o l'aggiunta di un'interfaccia JConsole per cercare il set di connessioni non chiuse nel codice in esecuzione, potrebbero essere entrambe buone opzioni.

Se il gestore connessioni non è il tuo codice, potresti comunque ottenere lo stesso risultato utilizzando aspetti.

+0

+1 per l'approccio AOP – teabot

+0

Il pool di connessione che usiamo fa qualcosa di molto simile a questo; Credo che avvolga le connessioni che restituisce e tiene traccia di quando vengono utilizzate. Se una connessione non viene utilizzata per un periodo di tempo superiore a quello specificato nella configurazione, la connessione verrà interrotta automaticamente e la traccia dello stack registrata sulla connessione aperta verrà stampata nel registro. – RMorrisey

0

È possibile implementare un mini-framework personalizzato o utilizzarne uno come thin wrapper su operazioni JDBC. Ad esempio, esiste un modulo spring-jdbc (mavenized) che copre tutto il codice di errore dello standard di caldaia dallo sviluppatore.

È possibile controllare il suo usage examples e vedere che non vi è alcuna inizializzazione/pulizia del codice cliente a tutti! Utilizza il modello 'metodo modello', ad esempio si scrive solo l'elaborazione dei dati essenziali e non si preoccupano delle connessioni/istruzioni/creazione e chiusura dei risultati. Quindi, non è possibile introdurre il problema che hai parlato in un primo momento.

Problemi correlati