Domanda

Ho un pool di connessioni MySQL per un servizio di dati web-based. Quando comincia a servire una richiesta, ci vuole una connessione dal pool da utilizzare. Il problema è che se c'è stata una pausa significativa da quel particolare connessione è stata utilizzata, il server potrebbe essere contati e chiuse sua fine. Mi piacerebbe essere in grado di rilevare questo nel codice di gestione della piscina.

Il trucco è questo: L'ambiente in cui sto codifica mi dà solo un API molto astratta nella connessione. Posso fondamentalmente solo eseguire le istruzioni SQL. Non ho accesso alla presa reale o l'accesso diretto al client API di MySQL.

Quindi, la domanda è: Qual è la dichiarazione MySQL più economico che posso eseguire sulla connessione per determinare se si sta lavorando. Per esempio SELECT 1; dovrebbe funzionare, ma mi chiedo se c'è qualcosa di ancora più conveniente? Forse qualcosa che non ha nemmeno andare attraverso il filo, ma viene gestito nel client lib MySQL ed efficacemente risponde alla stessa domanda?

Chiarimento: Io non sono preoccupato per verificare se il server MySQL è in esecuzione, o la configurazione del database se è è abbastanza per rispondere alle domande. Se queste cose sono in calo, quindi la successiva SQL viene eseguito il servizio otterrà e gestire l'errore. Sono veramente solo interessati con se la connessione TCP è aperto ... dal momento che se il server ha chiuso, quindi SQL del servizio web otterrà un errore che significa "solo ricollegare e riprovare", e che sarebbe scomodo da fare una volta verso il basso in il fango del codice di servizio.

di chiusura: L'hack /* ping */ è esattamente il genere di cose che stavo cercando, ma purtroppo è disponibile solo tramite JDBC. Leggendo la documentazione per che hack, è chiaro che è stato messo lì per esattamente lo stesso motivo ho voluto. Per i curiosi, sto lavorando in Haskel , utilizzando HDBC e HDBC-mysql . Ho intenzione di chiedere l'autore di HDBC-mysql per aggiungere un modo per chiamare mysql_ping() direttamente o tramite un hack simile.

DO 1 di Vlad era anche il tipo di cosa che cercavo, e dal momento che l'altro mod non è disponibile al di fuori di JDBC, sarò ad usarlo.

Grazie per tutte le grandi discussioni, in particolare @Vlad!

È stato utile?

Soluzione

non conoscere il vero stato della connessione senza andare oltre il filo , e SELECT 1 è un buon candidato abbastanza (forse si potrebbe trovare con un comando più breve, che richiede meno tempo per analizzare, ma rispetto alla rete o anche la latenza di loopback quel risparmio sarebbe irrilevante.)

Detto questo, direi che il ping di un collegamento prima estrarlo dalla piscina non è l'approccio migliore .

Probabilmente si dovrebbe semplicemente avere il vostro gestore di pool di connessione far rispettare la propria (timeout) la politica keep-alive per evitare di essere disconnessi dal server (a corto di un più grave problema di connettività intervento, che potrebbe influenzare nel bel mezzo delle operazioni regolari in ogni caso - e che la tua connessione Pool Manager non sarebbe in grado di aiutare con in ogni caso), così come al fine di non intasare il database (si pensi filehandles e utilizzo della memoria) inutilmente .

È quindi discutibile, a mio parere, ciò che il test il valore per la condizione di connettività prima della verificazione di una connessione dal pool ha davvero. Può valere la pena testare lo stato della connessione prima che una connessione viene controllato nel nuovo nella piscina , ma questo può essere fatto in modo implicito, semplicemente segnando la connessione come sporca quando un errore difficile SQL (o eccezione equivalente) si pone ( a meno che l'API si utilizza già espone una chiamata is-bad-come per voi.)

Vorrei quindi raccomandare:

  • l'attuazione di un policty keep-alive lato client
  • Non effettuare verifiche al momento del check out i collegamenti dalla piscina
  • l'esecuzione di controlli sporchi prima che una connessione viene restituito al pool
  • lasciare che il codice dell'applicazione accordo con altri (non-timeout) condizioni di connessione eccezionale

UPDATE

Sembrerebbe dai vostri commenti che davvero davvero desidera eseguire il ping il collegamento (suppongo che sia perché non si ha il pieno controllo su, o la conoscenza di, caratteristiche di timeout sul server MySQL o che intervengono apparecchiature di rete come proxy, ecc.)

In questo caso è possibile utilizzare DO 1 come alternativa SELECT 1; è marginalmente più veloce - più breve per analizzare, e non restituisce dati reali (anche se ottenere i acks TCP, quindi si continua a fare l'andata e ritorno convalidare che il connessione è ancora stabilita.)

UPDATE 2

Per quanto riguarda di Joshua posta , ecco pacchetto tracce di cattura per i vari scenari:

SELECT 1;
13:51:01.463112 IP client.45893 > server.mysql: P 2270604498:2270604511(13) ack 2531191393 win 1460 <nop,nop,timestamp 2983462950 59680547>
13:51:01.463682 IP server.mysql > client.45893: P 1:57(56) ack 13 win 65306 <nop,nop,timestamp 59680938 2983462950>
13:51:01.463698 IP client.45893 > server.mysql: . ack 57 win 1460 <nop,nop,timestamp 2983462951 59680938>

DO 1;
13:51:27.415520 IP client.45893 > server.mysql: P 13:22(9) ack 57 win 1460 <nop,nop,timestamp 2983488906 59680938>
13:51:27.415931 IP server.mysql > client.45893: P 57:68(11) ack 22 win 65297 <nop,nop,timestamp 59681197 2983488906>
13:51:27.415948 IP client.45893 > server.mysql: . ack 68 win 1460 <nop,nop,timestamp 2983488907 59681197>

mysql_ping
14:54:05.545860 IP client.46156 > server.mysql: P 69:74(5) ack 78 win 1460 <nop,nop,timestamp 2987247459 59718745>
14:54:05.546076 IP server.mysql > client.46156: P 78:89(11) ack 74 win 65462 <nop,nop,timestamp 59718776 2987247459>
14:54:05.546092 IP client.46156 > server.mysql: . ack 89 win 1460 <nop,nop,timestamp 2987247459 59718776>

Come si può vedere, tranne per il fatto che il pacchetto è mysql_ping 5 byte anziché 9 byte di DO 1;, il numero di andata e ritorno (e di conseguenza, rete indotta latenza) è esattamente lo stesso. L'unico costo aggiuntivo si paga con DO 1 al contrario di mysql_ping è l'analisi di DO 1, che è banale.

Altri suggerimenti

Non sono sicuro di quello che API che si sta utilizzando (o quale lingua), ma per Java, c'è un trucco speciale il driver JDBC può fare.

La query di prova standard è:

select 1

come hai indicato. Se si modifica a:

/* ping */ select 1

il driver JDBC noterà questo, e solo inviare un unico pacchetto al server MySQL per ottenere una risposta.

Ho imparato a conoscere questo ad un episodio di Sun 'Deep Dive' intitolato Consigli MySQL per sviluppatori Java Con Mark Matthews .

Anche se non si utilizza Java, forse questo stesso trucco è stato implementato in altri driver MySQL? Suppongo che il server avrebbe bisogno di essere a conoscenza di questo pacchetto speciale in modo che possa inviare una risposta ...

"Connessione" in questo caso ha molteplici significati. MySQL in ascolto su una socket- che è il livello di rete "di collegamento". MySQL mantiene "le connessioni al database", che comprendono un contesto per l'esecuzione di query e altre spese generali.

Se si vuole solo sapere se il servizio è in ascolto, si dovrebbe essere in grado di eseguire una chiamata a livello di rete per vedere se la porta (non so cosa il valore predefinito è) è in ascolto sul target IP. Se si desidera ottenere il motore MySQL a rispondere, penso che la tua idea SELECT 1 è buono- in realtà non recuperare i dati dal database, ma conferma che il motore è filata e rispondere.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top