Pool di connessioni di SQL Server con Microsoft.Data.SqlClient

Il pooling delle connessioni di Microsoft.Data.SqlClient riutilizza connessioni fisiche autenticate. SqlConnection.Open o OpenAsync verifica se nel pool è disponibile una connessione utilizzabile. Close, Dispose, oppure DisposeAsync lo resetta e lo restituisce. Questo approccio evita una connessione di rete, l'autenticazione e l'impostazione di sessione per ogni operazione.

Il pooling è abilitato di default. Usa questo schema applicativo:

await using var connection = new SqlConnection(connectionString);
await connection.OpenAsync(cancellationToken);

using var command = new SqlCommand(sql, connection);
await command.ExecuteNonQueryAsync(cancellationToken);

Apri fino a tardi, smalti in anticipo e lascia che la piscina gestisca le connessioni fisiche. Non lasciare un SqlConnection aperto a livello globale.

Comprendere le chiavi della piscina

Una connessione può essere riutilizzata solo dal pool corrispondente. La chiave del pool include più del solo server di destinazione.

Input Comportamento del pool
Stringa di connessione Il testo deve corrispondere esattamente. Le differenze nell'ordine delle parole chiave creano pool separati, anche quando le impostazioni effettive sono equivalenti.
Autenticazione integrata di Windows L'identità di Windows fa parte della chiave. La stessa stringa usata sotto identità diverse crea pool diversi.
SqlCredential L'istanza dell'oggetto fa parte della chiave. Istanze separate creano pool separati anche quando contengono lo stesso nome utente e password.
SqlConnection.AccessToken Il valore del token di accesso fa parte della chiave. Sostituire le stringhe di token può creare nuovi pool e lasciare le connessioni autenticate con i vecchi token in pool esistenti.
SqlConnection.AccessTokenCallback Il richiamo è parte della chiave. Riutilizza la stessa istanza di callback per connessioni che dovrebbero condividere un pool. Il valore del token restituito non è la chiave del pool.
Fornitore di contesto SSPI personalizzato L'istanza provider partecipa alla configurazione della connessione. Riutilizza un'istanza di provider per connessioni che dovrebbero essere aggregate.
Transazione implicita Le connessioni associate utilizzano suddivisioni specifiche della transazione all'interno del pool corrispondente.

Il database, la modalità di autenticazione, le opzioni di crittografia, il nome dell'applicazione, le opzioni di pooling e ogni altro valore della stringa di connessione contribuiscono tramite l'esatta stringa di connessione.

Crea una stringa di connessione canonica e riutilizzala. Evita valori specifici per richiesta in Application Name, Workstation ID oppure in altre parole chiave.

Scegli API di token che possano fare pool

Per i token di accesso Microsoft Entra ID, utilizza una modalità di autenticazione fornita da Microsoft. Data.SqlClient o un file stabile AccessTokenCallback.

AccessTokenCallbackè stato introdotto in Microsoft. Data.SqlClient 5.2. Il driver lo chiama quando ha bisogno di un token e può richiedere un token aggiornato per un pool riutilizzato. Mantieni il callback deterministico per i parametri di autenticazione forniti dal driver e riutilizza la stessa istanza delegata.

Quando il codice imposta AccessToken direttamente:

  • La stringa di token diventa parte della chiave del pool.
  • L'applicazione gestisce la scadenza e il rinnovo dei token.
  • Una connessione fisica aggregata può sopravvivere al token usato per crearla.
  • Chiama ClearPool dopo aver sostituito un token scaduto se quel pool non può più essere usato in sicurezza.

Non creare una nuova funzione lambda di callback o un nuovo oggetto credenziale per ogni richiesta. Le differenze di identità degli oggetti possono frammentare i pool.

Microsoft. Data.SqlClient 7.0 aggiunge SspiContextProvider per negoziazione personalizzata di Kerberos o NTLM. Tratta il provider come una configurazione di connessione a livello di applicazione, non come stato della singola richiesta.

Dimensiona ogni piscina

Queste opzioni di stringa di connessione controllano un pool:

Keyword Predefinito Effect
Pooling true Attiva o disattiva il pooling.
Min Pool Size 0 Stabilisce il numero minimo di connessioni fisiche che il pool mantiene dopo la sua creazione.
Max Pool Size 100 Imposta il numero massimo di connessioni fisiche nel pool.
Connect Timeout 15 secondi Stabilisce quanto tempo Open aspettare quando non c'è una connessione utilizzabile.
Load Balance Timeout 0 Secondi Scarta una connessione quando torna nel pool se la sua età supera il valore configurato. Connection Lifetime è un alias.

Il pool crea connessioni man mano che la domanda cresce fino a raggiungere Max Pool Size. Quando tutte le connessioni sono in uso, le aperture successive attendono il ritorno di una connessione. Se l'attesa supera Connect Timeout, l'apertura fallisce.

Non alzate Max Pool Size prima di aver controllato:

  • Ogni connessione e ogni lettore sono presenti su ciascun percorso.
  • Comandi e transazioni si concludono puntualmente.
  • Il carico di lavoro delle query non è bloccato né saturo.
  • Il limite di connessione al database può gestire Max Pool Size moltiplicato per ogni pool in ogni istanza dell'applicazione.

Un positivo Min Pool Size mantiene aperte le connessioni durante i periodi di inattività. Usalo solo quando le misurazioni giustificano connessioni calde. Di solito funziona contro design di cloud a scala a zero, auto-pausa serverless e cloud burstable.

Con il valore predefinito Load Balance Timeout=0, la pulizia periodica normalmente rimuove le connessioni inutilizzate sopra Min Pool Size dopo circa quattro-otto minuti, oppure il pool le rimuove quando rileva che la connessione server è interruta. Considera quell'intervallo come un comportamento di implementazione, non come una garanzia di inattività per ogni connessione. Il pool non invia una query di validazione prima di ogni checkout perché quel viaggio di andata e ritorno elimina gran parte del beneficio del pooling.

Gestire i periodi di blocco dell'autenticazione

Dopo un timeout di autenticazione o un altro fallimento dell'autenticazione, il pool può entrare in un periodo di blocco. Durante quel periodo, i tentativi di apertura corrispondenti generano nuovamente l'eccezione originale senza effettuare un nuovo tentativo di autenticazione.

Il primo periodo di blocco dura cinque secondi. Dopo un altro fallimento, il periodo raddoppia fino a un minuto.

Pool Blocking Period Controlla questo comportamento:

Valore Behavior
Auto Abilita il blocco per i normali endpoint SQL Server e lo disabilita per i suffissi Azure SQL riconosciuti. Un nome DNS vanity potrebbe non ricevere il comportamento Azure.
AlwaysBlock Abilita il periodo di blocco per ogni endpoint.
NeverBlock Disabilita il periodo di blocco.

Mantieni Auto a meno che la progettazione dei tentativi, definita in base alle misurazioni dell'applicazione, non richieda una scelta diversa. Disabilitare il periodo di blocco può trasformare un problema di credenziali, firewall o interruzione in una tempesta di autenticazione.

Il periodo di blocco è separato dal meccanismo di ritentativo configurabile. Un fornitore di ritentativi che apre lo stesso pool durante un periodo di blocco riceve l'eccezione nella cache.

Gestire la durata della connessione e la cancellazione

Il pool cancella automaticamente il pool interessato quando riconosce un errore fatale, come un failover. Il pool chiude le connessioni inattive e scarta le connessioni prelevate dal pool quando vengono restituite.

Usa le API di cancellazione per una configurazione nota o per un ambito delle credenziali noto:

  • ClearPool libera il pool associato a una configurazione SqlConnection .
  • ClearAllPoolscancella ogni pool Microsoft. Data.SqlClient nel processo o nel dominio applicativo.

Il pool chiude le connessioni inattive in un pool svuotato. Il pool contrassegna le connessioni attualmente in uso e le scarta quando vengono restituite al pool.

Lo svuotamento dei pool fa sì che le aperture successive eseguano accessi fisici. Non usarlo come manutenzione periodica, come gestore generale di errori o come sostituto per lo smaltimento delle connessioni.

Load Balance Timeout consente un ricambio graduale basato sull'età. Usalo quando una distribuzione o un servizio in cluster richiede che le vecchie connessioni fisiche vengano dismesse gradualmente nel tempo. Conferma che il valore scelto non causi connessioni rigide eccessive.

Transazioni

Con System.Transactions.Transaction.Current, il valore predefinito, una connessione aperta all'interno di Enlist=true viene automaticamente inclusa in quella transazione.

Quando una connessione associata a una transazione viene chiusa, il pool di connessioni la colloca in una suddivisione specifica per la transazione. Una successiva apertura con la stessa transazione può riutilizzarla. La connessione fisica non ritorna al pool generale finché la transazione non si completa.

Le transazioni ambientali lunghe o abbandonate possono quindi:

  • Escludi le connessioni fisiche dal pool generale.
  • Consumi la capacità del pool dopo la chiusura della connessione logica.
  • Mantieni attivi i blocchi dei server e lo stato delle transazioni.

Mantieni le transazioni limitate, completale esplicitamente e monitora le connessioni di stasi. Impostare Enlist=false solo quando la connessione deve rimanere al di fuori di una transazione di ambiente.

Prevenire la frammentazione del pool

La frammentazione dei pool crea molti piccoli pool invece di pochi pool riutilizzabili. Le cause più comuni includono:

  • Ordine delle parole chiave della stringa di connessione o differenze negli alias.
  • Una stringa di connessione per ogni cliente, utente, richiesta o database.
  • Autenticazione integrata sotto molte identità Windows.
  • Nuovi SqlCredential, callback del token di accesso o istanze del provider SSPI per ogni richiesta.
  • Token di accesso diretto che cambiano ad ogni aggiornamento.
  • Nomi di applicazioni ad alta cardinalità o ID di workstation.

Normalizzare le stringhe di connessione con SqlConnectionStringBuilder e centralizzare la creazione di connessioni.

Se l'applicazione si collega intenzionalmente a molti database o identità, includere il conteggio del pool risultante nella pianificazione della capacità. Non eseguire USE con un nome di database non attendibile per causare il collasso dei pool. L'isolamento del database, i permessi, lo stato della sessione e il comportamento di reset del pool devono rimanere espliciti.

Considerare i ruoli dell'applicazione e lo stato della sessione

Il pool resetta lo stato della sessione SQL Server riutilizzabile prima di assegnare una connessione fisica a un'altra connessione logica. Il codice applicativo dovrebbe comunque impostare lo stato di sessione richiesto all'interno della sua unità di lavoro.

I ruoli applicativi di SQL Server attivati con sp_setapprole non possono essere reimpostati in modo sicuro per il pooling ordinario. Preferisci utenti di database, utenti contenuti, ruoli, sicurezza a livello di riga o altro design di autorizzazione. Se un ruolo applicativo è inevitabile, utilizzare un modello di ripristino documentato basato sui cookie oppure disabilitare il pooling per quel percorso isolato dopo aver effettuato i test.

Elimina i lettori, completa o annulla le transazioni e non lasciare i comandi in esecuzione quando la connessione si chiude. Non affidarti a tabelle temporanee o a altri stati di sessione che sopravvivono tra connessioni logiche.

Usa modelli di pooling ospitati nel cloud

Per Servizio app di Azure, Funzioni di Azure, container, Kubernetes e altri host scalati orizzontalmente:

  • Calcola le possibili connessioni al database tra tutte le istanze, processi, chiavi di pool e repliche.
  • Usa un'identità gestita o un callback stabile di token di accesso invece di ruotare le stringhe di token negli oggetti di connessione.
  • Mantieni Min Pool Size=0 a meno che un requisito misurato relativo all'avvio a freddo non giustifichi sessioni persistenti.
  • Aspettati che una nuova istanza inizi con un pool vuoto.
  • Mantieni le stringhe di connessione identiche tra istanze che servono lo stesso carico di lavoro.
  • Limita i tentativi di connessione e i nuovi tentativi per evitare picchi di accessi sincronizzati durante il failover o lo scale-out.
  • Imposta MultiSubnetFailover=true per Azure SQL e altri endpoint TCP supportati con più indirizzi.

I pool di connessione sono locali al processo dell'applicazione. Non sono condivise tra istanze applicative, container o host.

Analizzare il comportamento del pool

Usa i contatori diagnostici SqlClient per osservare:

  • Connessioni e disconnessioni fisiche, che rappresentano connessioni fisiche del server.
  • Connessioni e disconnessioni soft, che rappresentano il prelievo e la restituzione dal pool.
  • Connessioni attive e disponibili del pool.
  • Gruppi e piscine attive.
  • Connessioni di stasi.
  • Connessioni recuperate nei casi in cui il codice applicativo non ha rilasciato la connessione logica.

Correla i contatori client con sessioni SQL Server, attese, blocchi e limiti di risorse. Un timeout del pool può significare una perdita di connessione, query lente, transazioni bloccate, troppa concorrenza, frammentazione del pool o un limite di capacità del database.

Usa il tracciamento EventSource per le tracce mirate del pooler. Il tracciamento è verboso. Abilitalo per una finestra diagnostica limitata e proteggi eventuali metadati di connessione catturati.

Elenco di controllo per la produzione

  • Mantieni il pooling attivato.
  • Riutilizza una stringa di connessione canonica per ogni carico di lavoro e database.
  • Elimina connessioni, comandi, lettori e transazioni su ogni percorso.
  • Riutilizza credenziali, token callback e istanze del provider SSPI.
  • Imposta timeout di connessione e dei comandi finiti.
  • Dimensiona il budget totale di connessione per ogni istanza applicativa.
  • Monitora connessioni fisiche, numero di pool, connessioni libere, blocchi e timeout.
  • Libera i pool solo per una credenziale, un token o un confine di configurazione che il provider non può rilevare, o quando la diagnostica conferma che le connessioni sono obsolete.
  • Verificare il comportamento dello scale-out nei test di carico, del failover e del rinnovo delle credenziali prima della messa in produzione.