Nuta
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Dotyczy: .NET Framework
.NET
Standard
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, należy przeprowadzić początkowe uzgadnianie z serwerem, należy przeanalizować informacje o parametrach połączenia, połączenie musi zostać uwierzytelnione przez serwer, należy przeprowadzić sprawdzanie w celu uczestnictwa 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ń, dostawca danych Microsoft SqlClient dla programu SQL Server używa techniki optymalizacji nazywanej buforowaniem połączeń.
Buforowanie połączeń zmniejsza liczbę przypadków, w których muszą być otwierane nowe połączenia.
Menedżer połączeń utrzymuje kontrolę nad własnością 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 na połączeniu, pooler szuka dostępnego połączenia w puli. Jeśli dostępne jest połączenie w puli, zwraca to połączenie do obiektu wywołującego zamiast otwierania nowego połączenia. Gdy aplikacja wywołuje Close na połączeniu, pooler zwraca je 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.
Tylko połączenia o tej samej konfiguracji mogą być grupowane. Dostawca danych Programu Microsoft SqlClient dla programu SQL Server przechowuje kilka pul jednocześnie — po jednym dla każdej konfiguracji. Połączenia są rozdzielane pulami według parametrów połączenia i tożsamości systemu Windows w przypadku użycia zintegrowanych zabezpieczeń. Połączenia są również grupowane w zależności od tego, czy są one uwzględnione w transakcji. W przypadku korzystania z ChangePassword, wystąpienie SqlCredential wpływa na pulę połączeń. Różne wystąpienia SqlCredential będą korzystać z różnych pul połączeń, nawet jeśli identyfikator użytkownika i hasło są takie same.
Grupowanie połączeń może znacznie zwiększyć wydajność i skalowalność aplikacji. Domyślnie buforowanie połączeń jest włączone w programie Microsoft SqlClient Data Provider dla programu SQL Server. 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 parametrów połączenia, aby kontrolować zachowanie puli połączeń. Aby uzyskać więcej informacji, zobacz "Kontrolowanie puli połączeń słowami kluczowymi w parametrach połączenia" w dalszej części tematu.
Ważne
Po włączeniu buforowania połączeń, jeśli wystąpi błąd przekroczenia limitu czasu lub inny błąd logowania, zgłoszony zostanie wyjątek, a kolejne próby połączenia nie powiodą się przez następne 5 sekund "blocking period". 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 1 minuta.
Uwaga / Notatka
Mechanizm "blocking period" nie ma zastosowania do programu Azure SQL Server domyślnie. Można zmienić to zachowanie, modyfikując właściwość PoolBlockingPeriod w ConnectionString, z wyjątkiem .NET Standard.
Tworzenie i przypisywanie puli
Po pierwszym otwarciu połączenia tworzona jest pula połączeń na podstawie algorytmu dokładnego dopasowania, który kojarzy pulę z ciągiem połączenia. Każda pula połączeń jest skojarzona z odrębnym ciągiem połączenia. Po otwarciu nowego połączenia, jeśli parametry połączenia nie są dokładnie zgodne z istniejącą pulą, zostanie utworzona nowa pula.
Uwaga / Notatka
Połączenia są gromadzone na proces, na domenę aplikacji, na parametry połączenia i przy użyciu zintegrowanych zabezpieczeń, 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.
Uwaga / Notatka
Jeśli MinPoolSize nie zostanie określony w parametrach 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ść MinPoolSize jest większa niż zero, pula połączeń nie zostanie zniszczona aż do momentu zwolnienia AppDomain i zakończenia procesu. Konserwacja nieaktywnych lub pustych pul obejmuje minimalne obciążenie systemu.
Uwaga / Notatka
Pula jest automatycznie czyszczona po wystąpieniu błędu krytycznego, takiego jak przełączenie awaryjne.
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.
}
Dodawanie połączeń
Pula połączeń jest tworzona dla każdego unikatowego parametru połączenia. Gdy pula jest tworzona, do niej zostaje dodanych wiele obiektów połączenia, aby spełnić minimalne wymaganie dotyczące jej rozmiaru. Połączenia są dodawane do puli zgodnie z potrzebami, do maksymalnego rozmiaru określonego dla puli (wartość domyślna to 100). Połączenia są zwalniane z powrotem do puli po ich zamknięciu lub usunięciu.
SqlConnection Gdy obiekt jest żądany, jest pobierany z puli, jeśli dostępne jest 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 puler próbuje odzyskać wszystkie połączenia, dopóki nie zostanie osiągnięty limit czasu (wartość domyślna to 15 sekund). Jeśli pooler nie może spełnić żądania przed upływem limitu czasu połączenia, wystąpi wyjątek.
Ostrzeżenie
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 metod Close lub Dispose obiektu Connection, albo otwierając wszystkie połączenia wewnątrz instrukcji using w języku C# lub instrukcji 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 / Notatka
Nie należy wywoływać Close ani Dispose na Connection, DataReader ani na żadnym innym obiekcie zarządzanym w metodzie Finalize twojej 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 Zbieranie śmieci.
Aby uzyskać więcej informacji na temat zdarzeń skojarzonych z otwieraniem i zamykaniem połączeń, zobacz Audit Login Event Class (Klasa zdarzeń logowania inspekcji) i Audit Logout Event Class (Klasa zdarzeń wylogowania inspekcji) w dokumentacji programu SQL Server.
Usuwanie połączeń
Jeśli parametr LoadBalanceTimeout (lub Connection Lifetime) jest ustawiony, gdy połączenie jest zwracane do puli, jego czas tworzenia jest porównywany z bieżącym czasem, a połączenie zostanie zniszczone, jeśli ten przedział czasu (w sekundach) przekroczy wartość określoną przez LoadBalanceTimeout. Jest to przydatne w konfiguracjach klastrowanych, aby wymusić równoważenie obciążenia między uruchomionym serwerem a serwerem właśnie przeniesionym w tryb online.
Jeśli parametr LoadBalanceTimeout (lub okres istnienia połączenia) nie jest ustawiony (wartość domyślna = 0), program puli połączeń usuwa połączenie z puli po bezczynności przez około 4–8 minut (w sposób losowy dwuprzepustowy) lub jeśli moduł puli wykryje, że połączenie z serwerem zostało zerwane.
Uwaga / Notatka
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ż koszty sprawdzania, czy połączenie jest nadal prawidłowe, wyeliminowałyby korzyści wynikających z używania menedżera połączeń 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ę
Dostawca danych Programu Microsoft SqlClient dla programu SQL Server wprowadził 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.
Uwaga / Notatka
Jeśli w momencie wywołania są używane połączenia, są one odpowiednio oznaczone. Gdy zostaną zamknięte, będą odrzucone zamiast zwrócone do puli.
Obsługa transakcji
Połączenia są pobierane z puli i przypisywane na podstawie kontekstu transakcji. Jeśli Enlist=false nie jest określony w parametrach połączenia, pula połączeń zapewnia, że połączenie jest zarejestrowane w Current kontekście. Gdy połączenie zostanie zamknięte i zwrócone do puli z zarejestrowaną transakcją System.Transactions, zostanie ono odłożone w taki sposób, że następne zapytanie o tę pulę połączeń z tą samą transakcją zwróci to samo połączenie System.Transactions, jeśli jest ono dostępne. Jeśli takie żądanie zostanie wystosowane i nie ma dostępnych połączeń w puli, połączenie jest pobierane z części puli nieprzeznaczonej dla transakcji i przypisywane do transakcji. Jeśli w żadnym z obszarów puli nie są dostępne żadne połączenia, zostanie utworzone nowe połączenie i dołączone do puli.
Po zamknięciu połączenia jest ono zwalniane z powrotem do puli i do odpowiedniej poddziałki na podstawie kontekstu transakcji. W związku z tym można zamknąć połączenie bez generowania błędu, mimo że transakcja rozproszona nadal jest w toku. To umożliwia zatwierdzenie lub anulowanie transakcji rozproszonej w późniejszym czasie.
Zarządzaj buforowaniem połączeń za pomocą słów kluczowych w parametrze połączenia
Właściwość ConnectionStringSqlConnection obiektu obsługuje pary klucz/wartość parametrów połączenia, 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ą grupowane w puli na podstawie łańcucha 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. Efekt uboczny wiąże się z konkretną architekturą aplikacji internetowej, którą deweloperzy muszą zrównoważyć z wymaganiami związanymi z bezpieczeństwem i audytem.
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 wspólne i używane przez wszystkich. 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 docelowej bazy danych określonej w zmiennej ciągu databaseName.
// Assume that connectionString connects to master.
using (SqlConnection connection = new SqlConnection(connectionString))
using (SqlCommand command = new SqlCommand())
{
connection.Open();
command.Connection = connection;
command.CommandText = "USE DatabaseName";
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 włączone jest korzystanie z puli, połączenie zostaje zwrócone do puli, a błąd występuje, gdy połączenie z puli jest ponownie używane.
Alternatywy roli aplikacji
Zalecamy korzystanie z mechanizmów zabezpieczeń, których można używać zamiast ról aplikacji.