Dela via


SQL Server-anslutningspooler (ADO.NET)

Att ansluta till en databasserver består vanligtvis av flera tidskrävande steg. En fysisk kanal som en socket eller ett namngivet rör måste upprättas, den första handskakningen med servern måste ske, anslutningssträng informationen måste parsas, anslutningen måste autentiseras av servern, kontroller måste köras för att registrera den aktuella transaktionen och så vidare.

I praktiken använder de flesta program bara en eller några olika konfigurationer för anslutningar. Det innebär att många identiska anslutningar öppnas och stängs upprepade gånger under programkörningen. För att minimera kostnaden för att öppna anslutningar använder ADO.NET en optimeringsteknik som kallas anslutningspooler.

Anslutningspooler minskar antalet gånger som nya anslutningar måste öppnas. Pooler behåller ägarskapet för den fysiska anslutningen. Den hanterar anslutningar genom att hålla en uppsättning aktiva anslutningar vid liv för varje angiven anslutningskonfiguration. När en användare anropar Open en anslutning letar poolverktyget efter en tillgänglig anslutning i poolen. Om en poolanslutning är tillgänglig returneras den till anroparen i stället för att öppna en ny anslutning. När programmet anropar Close anslutningen returnerar poolverktyget den till den poolade uppsättningen aktiva anslutningar i stället för att stänga den. När anslutningen har returnerats till poolen är den redo att återanvändas vid nästa Open anrop.

Endast anslutningar med samma konfiguration kan poolas. ADO.NET behåller flera pooler samtidigt, en för varje konfiguration. Anslutningar delas upp i pooler efter anslutningssträng och av Windows-identitet när integrerad säkerhet används. Anslutningar poolas också baserat på om de är registrerade i en transaktion. När du använder ChangePasswordpåverkar instansen SqlCredential anslutningspoolen. Olika instanser av SqlCredential använder olika anslutningspooler, även om användar-ID och lösenord är desamma.

Poolanslutningar kan avsevärt förbättra programmets prestanda och skalbarhet. Som standard är anslutningspooler aktiverade i ADO.NET. Om du inte uttryckligen inaktiverar det optimerar poolverktyget anslutningarna när de öppnas och stängs i ditt program. Du kan också ange flera anslutningssträng modifierare för att styra beteendet för anslutningspooler. Mer information finns i "Kontrollera anslutningspooler med nyckelord för anslutningssträngar" senare i det här avsnittet.

Kommentar

När anslutningspoolen är aktiverad, och om ett timeoutfel eller ett annat inloggningsfel inträffar, utlöses ett undantag och efterföljande anslutningsförsök misslyckas under de kommande fem sekunderna, "blockeringsperioden". Om programmet försöker ansluta inom blockeringsperioden utlöses det första undantaget igen. Efterföljande fel efter att en blockeringsperiod har upphört resulterar i nya blockeringsperioder som är dubbelt så långa som den föregående blockeringsperioden, upp till högst en minut.

Skapa och tilldela pool

När en anslutning öppnas först skapas en anslutningspool baserat på en exakt matchande algoritm som associerar poolen med anslutningssträng i anslutningen. Varje anslutningspool är associerad med en distinkt anslutningssträng. När en ny anslutning öppnas skapas en ny pool om anslutningssträng inte är en exakt matchning mot en befintlig pool. Anslutningar poolas per process, per programdomän, per anslutningssträng och när integrerad säkerhet används, per Windows-identitet. Anslutningssträngar måste också vara en exakt matchning. nyckelord som anges i en annan ordning för samma anslutning poolas separat.

I följande C#-exempel skapas tre nya SqlConnection objekt, men endast två anslutningspooler krävs för att hantera dem. Observera att den första och andra anslutningssträng skiljer sig från det tilldelade värdet för 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.
    }

Viktigt!

Microsoft rekommenderar att du använder det säkraste tillgängliga autentiseringsflödet. Om du ansluter till Azure SQL är hanterade identiteter för Azure-resurser den rekommenderade autentiseringsmetoden.

Om Min Pool Size inte anges i anslutningssträng eller anges som noll stängs anslutningarna i poolen efter en period av inaktivitet. Om den angivna Min Pool Size är större än noll förstörs dock inte anslutningspoolen förrän den AppDomain tas bort och processen avslutas. Underhåll av inaktiva eller tomma pooler innebär minimala systemkostnader.

Kommentar

Poolen rensas automatiskt när ett allvarligt fel inträffar, till exempel en redundansväxling.

Lägga till anslutningar

En anslutningspool skapas för varje unik anslutningssträng. När en pool skapas skapas flera anslutningsobjekt och läggs till i poolen så att minimikravet för poolstorlek uppfylls. Anslutningar läggs till i poolen efter behov, upp till den maximala poolstorleken som anges (100 är standard). Anslutningar släpps tillbaka till poolen när de stängs eller tas bort.

När ett SqlConnection objekt begärs hämtas det från poolen om det finns en användbar anslutning. För att kunna användas måste en anslutning vara oanvänd, ha en matchande transaktionskontext eller vara oassocierad med någon transaktionskontext och ha en giltig länk till servern.

Anslutningspoolen uppfyller begäranden om anslutningar genom att omplacera anslutningar när de släpps tillbaka till poolen. Om den maximala poolstorleken har nåtts och ingen användbar anslutning är tillgänglig placeras begäran i kö. Pooler försöker sedan återta alla anslutningar tills tidsgränsen nås (standardvärdet är 15 sekunder). Om pooler inte kan uppfylla begäran innan anslutningen överskrider tidsgränsen utlöses ett undantag.

Varning

Vi rekommenderar starkt att du alltid stänger anslutningen när du är klar med den så att anslutningen returneras till poolen. Du kan göra detta med antingen Close objektets metoder Connection eller Dispose genom att öppna alla anslutningar i en using instruktion i C#, eller en Using instruktion i Visual Basic. Anslutningar som inte är uttryckligen stängda kanske inte läggs till eller returneras till poolen. Mer information finns i Använda instruktion eller Så här gör du: Ta bort en systemresurs för Visual Basic.

Kommentar

Anropa Close inte eller Dispose på ett Connection, ett DataReader, eller något annat hanterat objekt i -metoden för Finalize din klass. I en finalizer släpper du bara ohanterade resurser som klassen äger direkt. Om klassen inte äger några ohanterade resurser ska du inte inkludera någon Finalize metod i din klassdefinition. Mer information finns i Skräpinsamling.

Mer information om händelser som är associerade med att öppna och stänga anslutningar finns i Granska händelseklass för inloggning och granskningshändelseklass för utloggning i SQL Server-dokumentationen.

Ta bort anslutningar

Anslutningspoolen tar bort en anslutning från poolen efter att den har varit inaktiv i cirka 4–8 minuter, eller om poolhanteraren upptäcker att anslutningen till servern har avbrutits. Observera att en avskuren anslutning endast kan identifieras när du har försökt kommunicera med servern. Om en anslutning hittas som inte längre är ansluten till servern markeras den som ogiltig. Ogiltiga anslutningar tas bara bort från anslutningspoolen när de stängs eller återtas.

Om det finns en anslutning till en server som har försvunnit kan den här anslutningen hämtas från poolen även om anslutningspoolen inte har identifierat den avhuggna anslutningen och markerat den som ogiltig. Detta är fallet eftersom omkostnaderna för att kontrollera att anslutningen fortfarande är giltig skulle eliminera fördelarna med att ha en pooler genom att orsaka en annan tur och retur till servern. När detta inträffar upptäcker det första försöket att använda anslutningen att anslutningen har avbrutits och ett undantag utlöses.

Rensa poolen

ADO.NET 2.0 introducerade två nya metoder för att rensa poolen: ClearAllPools och ClearPool. ClearAllPools rensar anslutningspoolerna för en viss provider och ClearPool rensar den anslutningspool som är associerad med en specifik anslutning. Om det finns anslutningar som används vid tidpunkten för anropet markeras de på rätt sätt. När de stängs ignoreras de i stället för att returneras till poolen.

Transaktionsstöd

Anslutningar hämtas från poolen och tilldelas baserat på transaktionskontext. Om inte Enlist=false anges i anslutningssträng ser anslutningspoolen till att anslutningen är angiven i kontextenCurrent. När en anslutning stängs och returneras till poolen med en listad transaktion, avsätts System.Transactions den på ett sådant sätt att nästa begäran för anslutningspoolen med samma System.Transactions transaktion returnerar samma anslutning om den är tillgänglig. Om en sådan begäran utfärdas och det inte finns några tillgängliga poolanslutningar, hämtas en anslutning från den icke-transacted delen av poolen och registreras. Om inga anslutningar är tillgängliga i något av poolområdet skapas och registreras en ny anslutning.

När en anslutning stängs släpps den tillbaka till poolen och till lämplig underindelning baserat på dess transaktionskontext. Därför kan du stänga anslutningen utan att generera ett fel, även om en distribuerad transaktion fortfarande väntar. På så sätt kan du checka in eller avbryta den distribuerade transaktionen senare.

Kontrollera anslutningspooler med nyckelord för anslutningssträng

Egenskapen ConnectionString för SqlConnection objektet stöder anslutningssträng nyckel/värde-par som kan användas för att justera beteendet för anslutningspoollogik. Mer information finns i ConnectionString.

Poolfragmentering

Poolfragmentering är ett vanligt problem i många webbprogram där programmet kan skapa ett stort antal pooler som inte frigörs förrän processen avslutas. Detta lämnar ett stort antal anslutningar öppna och förbrukar minne, vilket resulterar i dåliga prestanda.

Poolfragmentering på grund av integrerad säkerhet

Anslutningar poolas enligt anslutningssträng plus användaridentiteten. Om du använder Grundläggande autentisering eller Windows-autentisering på webbplatsen och en integrerad säkerhetsinloggning får du därför en pool per användare. Även om detta förbättrar prestandan för efterföljande databasbegäranden för en enskild användare kan den användaren inte dra nytta av anslutningar som görs av andra användare. Det resulterar också i minst en anslutning per användare till databasservern. Det här är en bieffekt av en viss webbprogramarkitektur som utvecklare måste väga mot säkerhets- och granskningskrav.

Poolfragmentering på grund av många databaser

Många Internetleverantörer är värdar för flera webbplatser på en enda server. De kan använda en enkel databas för att bekräfta inloggningen för formulärautentisering och sedan öppna en anslutning till en specifik databas för den användaren eller gruppen av användare. Anslutningen till autentiseringsdatabasen poolas och används av alla. Det finns dock en separat pool med anslutningar till varje databas, vilket ökar antalet anslutningar till servern.

Detta är också en bieffekt av programdesignen. Det finns ett relativt enkelt sätt att undvika den här sidoeffekten utan att äventyra säkerheten när du ansluter till SQL Server. I stället för att ansluta till en separat databas för varje användare eller grupp ansluter du till samma databas på servern och kör sedan Transact-SQL USE-instruktionen för att ändra till önskad databas. Följande kodfragment visar hur du skapar en första anslutning till master databasen och sedan växlar till önskad databas som anges i databaseName strängvariabeln.

' 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();
  }

Programroller och anslutningspooler

När en SQL Server-programroll har aktiverats genom att anropa den sp_setapprole system lagrade proceduren kan inte säkerhetskontexten för anslutningen återställas. Men om pooleringen är aktiverad returneras anslutningen till poolen och ett fel uppstår när den poolanslutna anslutningen återanvänds.

Se även