Udostępnij za pośrednictwem


Buforowanie połączeń z programem SQL Server (ADO.NET)

Nawiązywanie połączenia z serwerem bazy danych zwykle składa się z kilku czasochłonnych kroków. Należy ustanowić kanał fizyczny, taki jak gniazdo lub nazwany potok, początkowe uzgadnianie z serwerem, należy przeanalizować informacje parametry połączenia, połączenie musi zostać uwierzytelnione przez serwer, należy uruchomić sprawdzanie, aby zarejestrować się w bieżącej transakcji itd.

W praktyce większość aplikacji używa tylko jednej lub kilku różnych konfiguracji dla połączeń. Oznacza to, że podczas wykonywania aplikacji wiele identycznych połączeń będzie wielokrotnie otwieranych i zamykanych. Aby zminimalizować koszty otwierania połączeń, ADO.NET używa techniki optymalizacji nazywanej buforowaniem połączeń.

Buforowanie połączeń zmniejsza liczbę otwartych nowych połączeń. Program pooler utrzymuje własność połączenia fizycznego. Zarządza połączeniami, utrzymując aktywny zestaw aktywnych połączeń dla każdej konfiguracji połączenia. Za każdym razem, gdy użytkownik wywołuje Open połączenie, program pooler szuka dostępnego połączenia w puli. Jeśli połączenie w puli jest dostępne, zwraca je do obiektu wywołującego zamiast otwierania nowego połączenia. Gdy aplikacja wywołuje Close połączenie, program pooler zwraca go do zestawu aktywnych połączeń w puli, a nie zamyka go. Gdy połączenie zostanie zwrócone do puli, będzie gotowe do ponownego użycia podczas następnego Open wywołania.

Można pulować tylko połączenia z tą samą konfiguracją. ADO.NET jednocześnie przechowuje kilka pul, po jednym dla każdej konfiguracji. Połączenia są rozdzielane w pule przez parametry połączenia i przez tożsamość systemu Windows w przypadku użycia zintegrowanych zabezpieczeń. Połączenia są również w puli oparte na tym, czy są one wymienione w transakcji. W przypadku korzystania z ChangePasswordSqlCredential programu wystąpienie ma wpływ na pulę połączeń. Różne wystąpienia SqlCredential programu będą używać różnych pul połączeń, nawet jeśli identyfikator użytkownika i hasło są takie same.

Połączenia puli mogą znacznie zwiększyć wydajność i skalowalność aplikacji. Domyślnie buforowanie połączeń jest włączone w ADO.NET. Jeśli nie wyłączysz go jawnie, program pooler optymalizuje połączenia w miarę ich otwierania i zamykania w aplikacji. Można również podać kilka modyfikatorów parametry połączenia w celu kontrolowania zachowania puli połączeń. Aby uzyskać więcej informacji, zobacz "Kontrolowanie buforowania połączeń za pomocą słów kluczowych parametrów połączenia" w dalszej części tego tematu.

Uwaga

Po włączeniu buforowania połączeń i wystąpieniu błędu przekroczenia limitu czasu lub innego błędu logowania zostanie zgłoszony wyjątek, a kolejne próby nawiązania połączenia nie powiedzą się przez następne pięć sekund, "okres blokowania". Jeśli aplikacja spróbuje nawiązać połączenie w okresie blokowania, pierwszy wyjątek zostanie zgłoszony ponownie. Kolejne błędy po zakończeniu okresu blokowania spowodują powstanie nowych okresów blokowania, które są dwa razy większe niż poprzedni okres blokowania, maksymalnie minutę.

Tworzenie i przypisywanie puli

Po pierwszym otwarciu połączenia pula połączeń jest tworzona na podstawie dokładnego algorytmu dopasowania, który kojarzy pulę z parametry połączenia w połączeniu. Każda pula połączeń jest skojarzona z odrębnym parametry połączenia. Po otwarciu nowego połączenia, jeśli parametry połączenia nie jest dokładnie zgodny z istniejącą pulą, zostanie utworzona nowa pula. Połączenia są w puli na proces, na domenę aplikacji, na parametry połączenia i gdy są używane zintegrowane zabezpieczenia, na tożsamość systemu Windows. Parametry połączenia muszą być również dokładnie zgodne; słowa kluczowe podane w innej kolejności dla tego samego połączenia będą pulowane oddzielnie.

W poniższym przykładzie w języku C# są tworzone trzy nowe SqlConnection obiekty, ale do zarządzania nimi wymagane są tylko dwie pule połączeń. Należy pamiętać, że pierwsze i drugie parametry połączenia różnią się od wartości przypisanej dla elementu 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.
    }

Ważne

Firma Microsoft zaleca korzystanie z najbezpieczniejszego dostępnego przepływu uwierzytelniania. Jeśli łączysz się z usługą Azure SQL, tożsamości zarządzane dla zasobów platformy Azure to zalecana metoda uwierzytelniania.

Jeśli Min Pool Size nie zostanie określony w parametry połączenia lub zostanie określony jako zero, połączenia w puli zostaną zamknięte po okresie braku aktywności. Jeśli jednak określona wartość Min Pool Size jest większa niż zero, pula połączeń nie zostanie zniszczona do AppDomain czasu zwolnienia i zakończenia procesu. Konserwacja nieaktywnych lub pustych pul obejmuje minimalne obciążenie systemu.

Uwaga

Pula jest automatycznie czyszczone po wystąpieniu błędu krytycznego, takiego jak przejście w tryb failover.

Dodawanie połączeń

Pula połączeń jest tworzona dla każdego unikatowego parametry połączenia. Po utworzeniu puli zostanie utworzonych i dodanych wiele obiektów połączenia do puli, aby spełnić minimalne wymaganie dotyczące rozmiaru puli. Połączenia są dodawane do puli zgodnie z potrzebami, do maksymalnego rozmiaru puli określonej (wartość domyślna to 100). Połączenia są zwalniane z powrotem do puli po ich zamknięciu lub usunięciu.

SqlConnection Gdy zażądano obiektu, jest on uzyskiwany z puli, jeśli jest dostępne możliwe do użycia połączenie. Aby można było używać, połączenie musi być nieużywane, mieć zgodny kontekst transakcji lub nie być skojarzone z dowolnym kontekstem transakcji i mieć prawidłowy link do serwera.

Program puli połączeń spełnia żądania dotyczące połączeń przez ponowne przydzielanie połączeń w miarę ich zwalniania z powrotem do puli. Jeśli osiągnięto maksymalny rozmiar puli i nie jest dostępne żadne możliwe do użycia połączenie, żądanie jest kolejkowane. Następnie program puli próbuje odzyskać wszystkie połączenia do momentu osiągnięcia limitu czasu (wartość domyślna to 15 sekund). Jeśli program puli nie może spełnić żądania przed upływem limitu czasu połączenia, zostanie zgłoszony wyjątek.

Uwaga

Zdecydowanie zalecamy, aby zawsze zamykać połączenie po zakończeniu korzystania z niego, aby połączenie zostało zwrócone do puli. Można to zrobić przy użyciu Close metod Connection lub Dispose obiektu lub, otwierając wszystkie połączenia wewnątrz using instrukcji w języku C# lub instrukcję Using w języku Visual Basic. Połączenia, które nie są jawnie zamknięte, mogą nie zostać dodane lub zwrócone do puli. Aby uzyskać więcej informacji, zobacz using statement or How to: Dispose of a System Resource for Visual Basic (Jak usunąć zasób systemowy dla języka Visual Basic).

Uwaga

Nie należy wywoływać Close ani Dispose w Connectionobiekcie , ani DataReaderw żadnym innym obiekcie zarządzanym w Finalize metodzie klasy. W finalizatorze zwalniaj tylko niezarządzane zasoby, które należą do klasy bezpośrednio. Jeśli klasa nie jest właścicielem żadnych zasobów niezarządzanych, nie dołączaj Finalize metody do definicji klasy. Aby uzyskać więcej informacji, zobacz Odzyskiwanie pamięci.

Aby uzyskać więcej informacji na temat zdarzeń skojarzonych z otwieraniem i zamykaniem połączeń, zobacz Audit Login Event Class and Audit Logout Event Class (Klasa zdarzeń logowania inspekcji) i Audit Logout Event Class (Klasa zdarzeń wylogowywanie inspekcji) w dokumentacji programu SQL Server.

Usuwanie połączeń

Moduł puli połączeń usuwa połączenie z puli po bezczynności przez około 4–8 minut lub jeśli moduł puli wykryje, że połączenie z serwerem zostało zerwane. Należy pamiętać, że połączenie zerwane można wykryć dopiero po próbie nawiązania komunikacji z serwerem. Jeśli zostanie znalezione połączenie, które nie jest już połączone z serwerem, jest oznaczone jako nieprawidłowe. Nieprawidłowe połączenia są usuwane z puli połączeń tylko wtedy, gdy są zamknięte lub odzyskane.

Jeśli istnieje połączenie z serwerem, który zniknął, to połączenie można pobrać z puli, nawet jeśli moduł puli połączeń nie wykrył zerwanego połączenia i oznaczył go jako nieprawidłowe. Dzieje się tak, ponieważ obciążenie związane z sprawdzaniem, czy połączenie jest nadal prawidłowe, wyeliminowałoby korzyści wynikające z posiadania puli przez spowodowanie wystąpienia kolejnej rundy na serwerze. W takim przypadku pierwsza próba użycia połączenia wykryje, że połączenie zostało zerwane i zostanie zgłoszony wyjątek.

Wyczyść pulę

ADO.NET 2.0 wprowadzono dwie nowe metody czyszczenia puli: ClearAllPools i ClearPool. ClearAllPools czyści pule połączeń dla danego dostawcy i ClearPool czyści pulę połączeń skojarzona z określonym połączeniem. Jeśli w momencie wywołania są używane połączenia, są one odpowiednio oznaczone. Gdy zostaną zamknięte, zostaną one odrzucone, a nie zostaną zwrócone do puli.

Obsługa transakcji

Połączenia są pobierane z puli i przypisywane na podstawie kontekstu transakcji. O ile nie Enlist=false zostanie określony w parametry połączenia, pula połączeń upewnia się, że połączenie jest wymienione w Current kontekście. Gdy połączenie zostanie zamknięte i zwrócone do puli z transakcją enlisted System.Transactions , zostanie ono odłożone w taki sposób, że następne żądanie dla tej puli połączeń z tą samą transakcją zwróci to samo System.Transactions połączenie, jeśli jest dostępne. Jeśli takie żądanie jest wystawiane i nie ma dostępnych połączeń w puli, połączenie jest pobierane z części niezwiązanej z pulą i wymienione. Jeśli w żadnym obszarze puli nie są dostępne żadne połączenia, zostanie utworzone i wyświetlone nowe połączenie.

Po zamknięciu połączenia zostanie ono zwolnione z powrotem do puli i do odpowiedniej poddziału na podstawie kontekstu transakcji. W związku z tym można zamknąć połączenie bez generowania błędu, mimo że transakcja rozproszona jest nadal oczekująca. Dzięki temu można zatwierdzić lub przerwać transakcję rozproszoną później.

Kontrolowanie buforowania połączeń za pomocą słów kluczowych parametry połączenia

Właściwość ConnectionString SqlConnection obiektu obsługuje pary parametry połączenia klucz/wartość, których można użyć do dostosowania zachowania logiki buforowania połączeń. Aby uzyskać więcej informacji, zobacz ConnectionString.

Fragmentacja puli

Fragmentacja puli jest typowym problemem w wielu aplikacjach internetowych, w których aplikacja może utworzyć dużą liczbę pul, które nie zostaną zwolnione do momentu zakończenia procesu. Pozostawia to dużą liczbę połączeń otwartych i zużywających pamięć, co skutkuje niską wydajnością.

Fragmentacja puli ze względu na zintegrowane zabezpieczenia

Połączenia są w puli zgodnie z parametry połączenia oraz tożsamością użytkownika. W związku z tym, jeśli używasz uwierzytelniania podstawowego lub uwierzytelniania systemu Windows w witrynie sieci Web i zintegrowanego logowania zabezpieczeń, otrzymasz jedną pulę na użytkownika. Chociaż poprawia to wydajność kolejnych żądań bazy danych dla jednego użytkownika, ten użytkownik nie może korzystać z połączeń wykonanych przez innych użytkowników. Powoduje to również co najmniej jedno połączenie na użytkownika z serwerem bazy danych. Jest to efekt uboczny konkretnej architektury aplikacji internetowej, którą deweloperzy muszą rozważyć wymagania dotyczące zabezpieczeń i inspekcji.

Fragmentacja puli ze względu na wiele baz danych

Wielu dostawców usług internetowych hostuje kilka witryn sieci Web na jednym serwerze. Mogą używać pojedynczej bazy danych do potwierdzenia logowania do uwierzytelniania formularzy, a następnie otworzyć połączenie z określoną bazą danych dla tego użytkownika lub grupy użytkowników. Połączenie z bazą danych uwierzytelniania jest w puli i używane przez wszystkich użytkowników. Istnieje jednak oddzielna pula połączeń z każdą bazą danych, co zwiększa liczbę połączeń z serwerem.

Jest to również efekt uboczny projektu aplikacji. Istnieje stosunkowo prosty sposób uniknięcia tego efektu ubocznego bez naruszania zabezpieczeń podczas nawiązywania połączenia z programem SQL Server. Zamiast łączyć się z oddzielną bazą danych dla każdego użytkownika lub grupy, połącz się z tą samą bazą danych na serwerze, a następnie wykonaj instrukcję Transact-SQL USE, aby zmienić żądaną bazę danych. Poniższy fragment kodu przedstawia utworzenie początkowego połączenia z master bazą danych, a następnie przełączenie do żądanej bazy danych określonej w zmiennej databaseName ciągu.

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

Role aplikacji i buforowanie połączeń

Po aktywowaniu roli aplikacji programu SQL Server przez wywołanie sp_setapprole procedury składowanej systemu nie można zresetować kontekstu zabezpieczeń tego połączenia. Jeśli jednak pula jest włączona, połączenie jest zwracane do puli i występuje błąd podczas ponownego użycia połączenia w puli.

Zobacz też