Vai al contenuto
DedicatedPHP Contatto

Quando PHP esaurisce le connessioni al database: diagnosi e ripristino

Impara a distinguere le connessioni esaurite dalle query lente, misurare la concorrenza di PHP e recuperare capacità senza aumentare i limiti alla cieca.

Diagramma tecnico dei processi PHP, delle connessioni simultanee e del limite di connessioni di un database

L'esaurimento delle connessioni al database in PHP si manifesta spesso con errori intermittenti: alcune richieste falliscono, altre restano in attesa e il problema peggiora nelle ore di maggiore carico. Aumentare il limite di connessioni può alleviare la situazione, ma può anche trasferire la saturazione al server del database. La soluzione inizia identificando quale risorsa si esaurisce e chi mantiene occupate le connessioni.

Riconosci i sintomi e circoscrivi il problema

Riconosci i sintomi e circoscrivi il problema — guía visual de DedicatedPHP

Cerca errori come «too many connections», errori nell'apertura di una connessione, timeout o richieste che superano il tempo massimo di esecuzione. Confrontane la frequenza con il traffico e con altri indicatori: latenza dell'applicazione, uso di CPU e memoria, errori del database e durata delle richieste.

La differenza tra carico alto e basso offre un primo indizio. Se gli errori compaiono durante i picchi e scompaiono quando il traffico diminuisce, potrebbe esserci un limite di concorrenza. Se persistono anche con poche richieste, indaga sulle connessioni trattenute, sui processi bloccati, sulle query prolungate o su un database inaccessibile. Verifica anche se altri servizi condividono lo stesso limite: PHP non è necessariamente l'unico utilizzatore.

Distingui le connessioni esaurite dalle query lente e dai blocchi

Sono problemi correlati, ma non equivalenti. L'esaurimento delle connessioni si verifica quando non ci sono slot disponibili per aprirne un'altra. Una query lenta occupa una connessione più a lungo e, accumulandosi, può causare l'esaurimento. Un blocco lascia una query in attesa che un'altra transazione liberi risorse. L'indisponibilità significa che il database non può accettare o gestire connessioni per una causa più ampia.

Esamina il messaggio e il punto in cui si verifica l'errore. Se la richiesta fallisce prima di eseguire una query, verifica la creazione delle connessioni e il limite raggiunto. Se riesce a connettersi e poi impiega molto tempo, controlla le query in corso, la loro durata, le attese e le transazioni aperte. Non concludere che «mancano connessioni» solo perché l'applicazione risponde lentamente: aumentare il limite non risolve una query costosa né un blocco.

Metti in relazione la concorrenza di PHP con il limite del database

Nel modello abituale di PHP con processi che gestiscono le richieste, ogni processo può avere bisogno di una connessione mentre esegue operazioni sul database. La domanda potenziale dipende dal numero di processi che possono operare contemporaneamente, da quante connessioni apre ciascuno e da quanto a lungo le mantiene. È necessario conteggiare anche le connessioni usate dai job in background, dai comandi da console e dagli altri servizi.

Fai una stima prudenziale del caso peggiore: moltiplica la concorrenza massima effettiva di ciascun gruppo di processi per il numero di connessioni simultanee utilizzabili da ogni processo e somma gli altri consumatori che condividono il database. Confronta il risultato con il limite configurato e lascia margine per le operazioni amministrative e le variazioni di carico. Non presumere che ogni richiesta corrisponda sempre a una connessione: il ciclo di vita dipende dal client del database, dalla configurazione e dal modello di utilizzo.

Verifica anche come viene distribuito il carico. Più istanze PHP possono rispettare i propri limiti locali e, ciononostante, superare nel complesso il limite del database. Lo scaling orizzontale aumenta la concorrenza potenziale; non è una mitigazione sicura se non si ricalcola il totale delle connessioni.

Misura da entrambe le estremità

Correla le metriche dell'applicazione e del database usando timestamp. In PHP, registra la durata delle richieste, gli errori di connessione, i timeout e il numero di processi occupati. Nel database, controlla il numero di connessioni attive e il massimo raggiunto, i rifiuti, le query in esecuzione, l'età delle sessioni e le attese disponibili nel motore.

Evita di registrare credenziali, stringhe di connessione complete o dati sensibili delle query. Se il motore permette di identificare sessioni e stati, usali per distinguere una connessione inattiva da una query attiva o da una transazione in sospeso. Confronta i log dei due lati: un picco di connessioni simultaneo a processi PHP occupati indica un problema di concorrenza; molte sessioni vecchie o processi inattivi suggeriscono che le connessioni vengono trattenute; poche query di lunga durata possono spiegare perché il limite si consuma gradualmente.

La strumentazione deve permettere di rispondere a tre domande: quante connessioni vengono usate, quanto durano e quale attività le mantiene occupate. Senza questa cronologia, modificare i limiti o attivare le connessioni persistenti introduce altre variabili e rende più difficile individuare la causa.

Valuta le connessioni persistenti e di lunga durata

Una connessione persistente può ridurre il costo di apertura ripetuta delle connessioni, soprattutto quando l'ambiente mantiene i processi attivi tra una richiesta e l'altra. Tuttavia, una connessione che rimane associata a un processo può occupare uno slot anche quando non esegue query. Se ci sono molti processi o più istanze, l'insieme delle connessioni trattenute può raggiungere il limite del database.

Verifica il ciclo di vita effettivo del processo e del driver prima di attivarle o disattivarle. Controlla come viene riutilizzata la sessione e se l'applicazione ripristina lo stato previsto tra una richiesta e l'altra, ad esempio transazioni, variabili di sessione o configurazioni specifiche della connessione. Le connessioni persistenti non sono un pool universale e non garantiscono un consumo inferiore; provale sotto un carico rappresentativo e osserva il numero massimo di connessioni, la latenza e lo stato residuo.

Mitiga in ordine e sulla base di evidenze

  1. Limita la concorrenza. Regola il numero di processi PHP o il parallelismo dei worker affinché la domanda simultanea sia compatibile con il limite condiviso. Riduce la pressione, ma può aumentare la coda e la latenza se la capacità è inferiore alla domanda sostenuta.
  2. Libera le risorse quando non servono più. Chiudi esplicitamente le connessioni se la libreria e il modello di esecuzione lo consentono, ed evita di mantenerle durante attività estranee al database. Tieni presente che chiudere una connessione persistente non libera necessariamente la connessione fisica sul server: il risultato dipende dal driver e dal ciclo di vita del processo. Verifica le transazioni rimaste aperte e i percorsi di errore che non completano la pulizia.
  3. Riduci il tempo di occupazione. Analizza le query lente, gli indici, il volume dei risultati e le transazioni. Ottimizzare un'operazione che trattiene a lungo una connessione può ridurre la domanda simultanea senza aumentare il limite.
  4. Modifica i limiti solo dopo aver misurato. Aumentare il massimo può essere ragionevole se il database dispone ancora di capacità di CPU e memoria e il nuovo caso peggiore è sostenibile. Altrimenti, consente l'accumulo di altro lavoro e aggrava la saturazione.

Applica una modifica alla volta, registra lo stato precedente e definisci una condizione di rollback. Se il sistema è già sotto pressione, ridurre temporaneamente la concorrenza può essere più sicuro che riavviare tutti i processi contemporaneamente, perché ciò potrebbe creare un nuovo picco di connessioni.

Quando valutare un pool o un proxy di connessioni

Un pool o un proxy può riutilizzare le connessioni fisiche e controllare quante ne raggiungono il motore; può essere utile quando ci sono molti processi applicativi con connessioni di breve durata. Non elimina il lavoro simultaneo né rende più veloci le query; introduce un ulteriore livello con capacità, code, limiti e modalità operative proprie.

Prima di adottarlo, verifica la compatibilità con il motore, il driver PHP, l'autenticazione, l'uso delle transazioni e lo stato della sessione. Esamina come gestisce le connessioni di lunga durata, le riconnessioni e i guasti del proxy, e definisci metriche e procedure operative. Convalida la soluzione con test che riproducano la concorrenza reale: una configurazione che funziona in sviluppo può comportarsi diversamente sotto pressione.

Prepara il ripristino ed evita che il problema si ripeta

Prepara il ripristino ed evita che il problema si ripeta — guía visual de DedicatedPHP

Imposta avvisi per le connessioni vicine al limite, i rifiuti, la durata delle query e la saturazione dei processi PHP. Aggiungi un test di carico rappresentativo che includa istanze, job in background e altri consumatori; verifica il caso peggiore, non solo la media. Mantieni una procedura operativa che indichi cosa misurare, come limitare la concorrenza, chi può modificare il limite e quando eseguire il rollback.

Dopo aver ripristinato il servizio, esamina la sequenza che ha preceduto l'incidente: variazioni del traffico, deploy, nuove query, aumento dei processi o errori di pulizia. L'obiettivo è collegare causa ed effetto con i dati. Se le metriche mostrano connessioni trattenute, correggine il ciclo di vita; se prevale la durata delle query, ottimizzale; se la concorrenza legittima supera la capacità, dimensiona e limita il sistema con un budget esplicito di connessioni.

Vuoi applicare queste idee al tuo progetto?Parliamo della tua piattaforma PHP.
Visualizza il servizio correlato