SQL Server-verbindingspooling (ADO.NET)
Verbinding maken met een databaseserver bestaat doorgaans uit verschillende tijdrovende stappen. Een fysiek kanaal, zoals een socket of een benoemde pijp, moet tot stand worden gebracht, de eerste handshake met de server moet plaatsvinden, de verbindingsreeks informatie moet worden geparseerd, de verbinding moet worden geverifieerd door de server, er moeten controles worden uitgevoerd om in te schakelen in de huidige transactie, enzovoort.
In de praktijk gebruiken de meeste toepassingen slechts één of enkele verschillende configuraties voor verbindingen. Dit betekent dat tijdens het uitvoeren van de toepassing veel identieke verbindingen herhaaldelijk worden geopend en gesloten. Om de kosten van het openen van verbindingen te minimaliseren, gebruikt ADO.NET een optimalisatietechniek die verbindingspooling wordt genoemd.
Het groeperen van verbindingen vermindert het aantal keren dat nieuwe verbindingen moeten worden geopend. De pooler behoudt het eigendom van de fysieke verbinding. Het beheert verbindingen door een set actieve verbindingen in leven te houden voor elke opgegeven verbindingsconfiguratie. Wanneer een gebruiker een verbinding aanroept Open
, zoekt de pooler naar een beschikbare verbinding in de pool. Als er een gegroepeerde verbinding beschikbaar is, wordt deze teruggezet naar de beller in plaats van een nieuwe verbinding te openen. Wanneer de toepassing de verbinding aanroept, retourneert Close
de pooler deze naar de gegroepeerde set actieve verbindingen in plaats van deze te sluiten. Zodra de verbinding naar de pool is geretourneerd, is deze klaar om opnieuw te worden gebruikt bij de volgende Open
aanroep.
Alleen verbindingen met dezelfde configuratie kunnen worden gegroepeerd. ADO.NET meerdere pools tegelijk houdt, één voor elke configuratie. Verbindingen worden gescheiden in pools door verbindingsreeks en door Windows-identiteit wanneer geïntegreerde beveiliging wordt gebruikt. Verbindingen worden ook gegroepeerd op basis van of ze zijn opgenomen in een transactie. Wanneer u dit gebruikt ChangePassword, is het SqlCredential exemplaar van invloed op de verbindingsgroep. Verschillende exemplaren van SqlCredential zullen verschillende verbindingsgroepen gebruiken, zelfs als de gebruikers-id en het wachtwoord hetzelfde zijn.
Het groeperen van verbindingen kan de prestaties en schaalbaarheid van uw toepassing aanzienlijk verbeteren. Verbindingspooling is standaard ingeschakeld in ADO.NET. Tenzij u deze expliciet uitschakelt, optimaliseert de pooler de verbindingen zodra deze worden geopend en gesloten in uw toepassing. U kunt ook verschillende verbindingsreeks modifiers opgeven om het gedrag van verbindingsgroepen te beheren. Zie 'Verbindingsgroepen beheren met trefwoorden voor verbindingsreeksen' verderop in dit onderwerp voor meer informatie.
Notitie
Wanneer groepsgewijze verbindingen is ingeschakeld en er een time-outfout of een andere aanmeldingsfout optreedt, wordt er een uitzondering gegenereerd en mislukken volgende verbindingspogingen voor de komende vijf seconden, de 'blokkeringsperiode'. Als de toepassing probeert verbinding te maken binnen de blokkeringsperiode, wordt de eerste uitzondering opnieuw gegenereerd. Volgende fouten na een blokkeringsperiode resulteren in een nieuwe blokkeringsperiode die twee keer zo lang is als de vorige blokkeringsperiode, tot maximaal één minuut.
Pool maken en toewijzen
Wanneer een verbinding voor het eerst wordt geopend, wordt er een verbindingsgroep gemaakt op basis van een exact overeenkomend algoritme dat de pool koppelt aan de verbindingsreeks in de verbinding. Elke verbindingsgroep is gekoppeld aan een afzonderlijke verbindingsreeks. Wanneer er een nieuwe verbinding wordt geopend, wordt er een nieuwe pool gemaakt als de verbindingsreeks niet exact overeenkomt met een bestaande pool. Verbindingen worden gegroepeerd per proces, per toepassingsdomein, per verbindingsreeks en wanneer geïntegreerde beveiliging wordt gebruikt, per Windows-identiteit. Verbindingsreeksen moeten ook een exacte overeenkomst zijn; trefwoorden die in een andere volgorde voor dezelfde verbinding worden opgegeven, worden afzonderlijk gegroepeerd.
In het volgende C#-voorbeeld worden drie nieuwe SqlConnection objecten gemaakt, maar er zijn slechts twee verbindingsgroepen vereist om ze te beheren. Houd er rekening mee dat de eerste en tweede verbindingsreeks verschillen met de waarde die is toegewezen voor Initial Catalog
.
using (SqlConnection connection = new SqlConnection(
"Integrated Security=SSPI;Initial Catalog=Northwind"))
{
connection.Open();
// Pool A is created.
}
using (SqlConnection connection = new SqlConnection(
"Integrated Security=SSPI;Initial Catalog=pubs"))
{
connection.Open();
// Pool B is created because the connection strings differ.
}
using (SqlConnection connection = new SqlConnection(
"Integrated Security=SSPI;Initial Catalog=Northwind"))
{
connection.Open();
// The connection string matches pool A.
}
Belangrijk
Microsoft raadt u aan de veiligste verificatiestroom te gebruiken die beschikbaar is. Als u verbinding maakt met Azure SQL, is Managed Identities voor Azure-resources de aanbevolen verificatiemethode.
Als Min Pool Size
deze niet is opgegeven in de verbindingsreeks of als nul is opgegeven, worden de verbindingen in de pool gesloten na een periode van inactiviteit. Als de opgegeven Min Pool Size
waarde echter groter is dan nul, wordt de verbindingsgroep pas vernietigd nadat de AppDomain
verbinding is uitgepakt en het proces wordt beëindigd. Onderhoud van inactieve of lege pools omvat minimale systeemoverhead.
Notitie
De pool wordt automatisch gewist wanneer er een fatale fout optreedt, zoals een failover.
Verbindingen toevoegen
Er wordt een verbindingsgroep gemaakt voor elke unieke verbindingsreeks. Wanneer een pool wordt gemaakt, worden er meerdere verbindingsobjecten gemaakt en toegevoegd aan de pool, zodat aan de minimale grootte van de pool wordt voldaan. Verbindingen worden indien nodig aan de pool toegevoegd, tot de maximale grootte van de opgegeven pool (100 is de standaardgrootte). Verbindingen worden weer in de pool vrijgegeven wanneer ze worden gesloten of verwijderd.
Wanneer een SqlConnection object wordt aangevraagd, wordt het verkregen uit de pool als er een bruikbare verbinding beschikbaar is. Om bruikbaar te zijn, moet een verbinding ongebruikt zijn, een overeenkomende transactiecontext hebben of niet zijn gekoppeld aan een transactiecontext en een geldige koppeling hebben naar de server.
De verbindingspooler voldoet aan aanvragen voor verbindingen door verbindingen opnieuw te verplaatsen naarmate ze weer in de pool worden vrijgegeven. Als de maximale poolgrootte is bereikt en er geen bruikbare verbinding beschikbaar is, wordt de aanvraag in de wachtrij geplaatst. De pooler probeert vervolgens verbindingen vrij te maken totdat de time-out is bereikt (de standaardwaarde is 15 seconden). Als de pooler niet aan de aanvraag kan voldoen voordat er een time-out optreedt voor de verbinding, wordt er een uitzondering gegenereerd.
Let op
We raden u ten zeerste aan de verbinding altijd te sluiten wanneer u klaar bent met het gebruik, zodat de verbinding wordt geretourneerd naar de pool. U kunt dit doen met behulp van de Close
of Dispose
methoden van het Connection
object, of door alle verbindingen in een using
instructie in C# of een Using
instructie in Visual Basic te openen. Verbindingen die niet expliciet zijn gesloten, worden mogelijk niet toegevoegd of geretourneerd aan de pool. Zie voor meer informatie het gebruik van instructies of procedures: een systeemresource verwijderen voor Visual Basic.
Notitie
Roep een of ander beheerd object niet aan of Dispose
op een Connection
DataReader
ander beheerd object in de Finalize
methode van uw Close
klasse. In een finalizer kunt u alleen onbeheerde resources vrijgeven die rechtstreeks eigendom zijn van uw klasse. Als uw klasse geen onbeheerde resources bezit, neemt u Finalize
geen methode op in uw klassedefinitie. Zie Garbagecollection voor meer informatie.
Zie Gebeurtenisklasse voor auditaanmelding en afmeldingsgebeurtenisklasse controleren in de DOCUMENTATIE van SQL Server voor meer informatie over de gebeurtenissen die zijn gekoppeld aan het openen en sluiten van verbindingen.
Verbindingen verwijderen
De verbindingspooler verwijdert een verbinding uit de pool nadat deze ongeveer 4-8 minuten inactief is geweest of als de pooler detecteert dat de verbinding met de server is verbroken. Houd er rekening mee dat een verbroken verbinding alleen kan worden gedetecteerd nadat u hebt geprobeerd met de server te communiceren. Als er een verbinding wordt gevonden die niet meer is verbonden met de server, wordt deze gemarkeerd als ongeldig. Ongeldige verbindingen worden alleen uit de verbindingsgroep verwijderd wanneer ze worden gesloten of vrijgemaakt.
Als er een verbinding bestaat met een server die is verdwenen, kan deze verbinding worden getrokken uit de pool, zelfs als de verbindingspooler de verbroken verbinding niet heeft gedetecteerd en gemarkeerd als ongeldig. Dit is het geval omdat de overhead van het controleren of de verbinding nog steeds geldig is, de voordelen van het hebben van een pooler elimineert door een andere retour naar de server te veroorzaken. Wanneer dit gebeurt, wordt bij de eerste poging om de verbinding te gebruiken gedetecteerd dat de verbinding is verbroken en wordt er een uitzondering gegenereerd.
Het zwembad wissen
ADO.NET 2.0 heeft twee nieuwe methoden geïntroduceerd om de pool te wissen: ClearAllPools en ClearPool. ClearAllPools
wist de verbindingsgroepen voor een bepaalde provider en ClearPool
wist de verbindingsgroep die is gekoppeld aan een specifieke verbinding. Als er verbindingen worden gebruikt op het moment van de oproep, worden ze op de juiste manier gemarkeerd. Wanneer ze gesloten zijn, worden ze verwijderd in plaats van terug te keren naar de pool.
Transactieondersteuning
Verbindingen worden opgehaald uit de pool en toegewezen op basis van transactiecontext. Enlist=false
Tenzij deze is opgegeven in de verbindingsreeks, zorgt de verbindingsgroep ervoor dat de verbinding in de Current context wordt opgenomen. Wanneer een verbinding wordt gesloten en geretourneerd naar de pool met een in de lijst opgenomen transactie, wordt deze op zodanige System.Transactions
wijze gereserveerd dat de volgende aanvraag voor die verbindingsgroep met dezelfde System.Transactions
transactie dezelfde verbinding retourneert als deze beschikbaar is. Als een dergelijk verzoek wordt uitgegeven en er geen gegroepeerde verbindingen beschikbaar zijn, wordt er een verbinding gemaakt vanuit het niet-verwerkte deel van de pool en is er een verbinding opgenomen. Als er geen verbindingen beschikbaar zijn in een van beide gebieden van de pool, wordt er een nieuwe verbinding gemaakt en in de lijst opgenomen.
Wanneer een verbinding wordt gesloten, wordt deze weer in de pool en in de juiste onderverdeling vrijgegeven op basis van de transactiecontext. Daarom kunt u de verbinding sluiten zonder een fout te genereren, ook al is een gedistribueerde transactie nog in behandeling. Hierdoor kunt u de gedistribueerde transactie later doorvoeren of afbreken.
Groepsgewijze verbindingen beheren met verbindingsreeks trefwoorden
De ConnectionString
eigenschap van het SqlConnection object ondersteunt verbindingsreeks sleutel-/waardeparen die kunnen worden gebruikt om het gedrag van de verbindingsgroeplogica aan te passen. Zie ConnectionString voor meer informatie.
Poolfragmentatie
Poolfragmentatie is een veelvoorkomend probleem in veel webtoepassingen waarbij de toepassing een groot aantal pools kan maken die niet worden vrijgemaakt totdat het proces wordt afgesloten. Hierdoor blijft een groot aantal verbindingen open en verbruikend geheugen, wat resulteert in slechte prestaties.
Poolfragmentatie vanwege geïntegreerde beveiliging
Verbindingen worden gegroepeerd op basis van de verbindingsreeks plus de gebruikersidentiteit. Als u basisverificatie of Windows-verificatie gebruikt op de website en een geïntegreerde beveiligingsaanmelding, krijgt u dus één groep per gebruiker. Hoewel dit de prestaties van volgende databaseaanvragen voor één gebruiker verbetert, kan die gebruiker niet profiteren van verbindingen die door andere gebruikers zijn gemaakt. Het resulteert ook in ten minste één verbinding per gebruiker met de databaseserver. Dit is een neveneffect van een bepaalde webtoepassingsarchitectuur die ontwikkelaars moeten afwegen tegen beveiligings- en controlevereisten.
Poolfragmentatie vanwege veel databases
Veel internetproviders hosten verschillende websites op één server. Ze kunnen één database gebruiken om een aanmelding bij formulierverificatie te bevestigen en vervolgens een verbinding te openen met een specifieke database voor die gebruiker of groep gebruikers. De verbinding met de verificatiedatabase wordt gegroepeerd en door iedereen gebruikt. Er is echter een afzonderlijke groep verbindingen met elke database, waardoor het aantal verbindingen met de server wordt verhoogd.
Dit is ook een neveneffect van het toepassingsontwerp. Er is een relatief eenvoudige manier om dit neveneffect te voorkomen zonder de beveiliging in gevaar te brengen wanneer u verbinding maakt met SQL Server. In plaats van verbinding te maken met een afzonderlijke database voor elke gebruiker of groep, maakt u verbinding met dezelfde database op de server en voert u vervolgens de Transact-SQL USE-instructie uit om te wijzigen in de gewenste database. Het volgende codefragment laat zien hoe u een eerste verbinding met de master
database maakt en vervolgens overschakelt naar de gewenste database die is opgegeven in de databaseName
tekenreeksvariabele.
' Assumes that command is a SqlCommand object.
command.Text = "USE DatabaseName"
Using connection As New SqlConnection(connectionString)
connection.Open()
command.ExecuteNonQuery()
End Using
// Assumes that command is a SqlCommand object.
command.Text = "USE DatabaseName";
using (SqlConnection connection = new SqlConnection(
connectionString))
{
connection.Open();
command.ExecuteNonQuery();
}
Toepassingsrollen en groepsgewijze verbindingen
Nadat een SQL Server-toepassingsrol is geactiveerd door het aanroepen van de sp_setapprole
door het systeem opgeslagen procedure, kan de beveiligingscontext van die verbinding niet opnieuw worden ingesteld. Als pooling echter is ingeschakeld, wordt de verbinding teruggezet naar de pool en treedt er een fout op wanneer de poolverbinding opnieuw wordt gebruikt.
Zie ook
- Groepsgewijze verbinding
- SQL Server en ADO.NET
- Performance Counters (Prestatiemeteritems)
- overzicht van ADO.NET