2017-06-24 48 views
10

Walczymy z tym problemem w produkcji, gdy nasza wydajność baz danych SQL Azure ulega znacznemu pogorszeniu. Wiemy, że mamy blokady na jednym ze stołów, ale te blokady nie są blokadami, są one długimi blokadami i po około godzinie wydajność wraca do normy. Próbujemy znaleźć wszystkie możliwe scenariusze, w jaki sposób uzyskujemy te długie blokady (każde zapytanie jest superszybkie, a wszystkie analizatory wydajności mogą pokazać nam, co powoduje długie blokady). Powodem tej kwestii jest obraz poniżej:Aktywne połączenia usługi Azure Sql przekraczają limit pul połączeń.

enter image description here

Out ustawień puli połączeń pozwalają tylko 200 połączeń mają być połączone. A większość razy mamy około 10-20 połączeń otwartych/połączonych z bazą danych. Wtedy nagle liczba aktywnych połączeń zaczyna rosnąć, a pula jest całkowicie zajęta. Podczas gdy liczba połączonych połączeń utrzymuje się poniżej 200, widzimy wiele aktywnych połączeń za pomocą sp_who2 osiągających połączenia 1,5k-2k (czasami 4k-5k).

Zbudowałem ten sam wykres za pomocą narzędzi do monitorowania portalu Azure. Ma inny okres rozliczeniowy, ale pokazuje ten sam problem: enter image description here

ciąg połączenia używamy:

Data Source = [serwer] .database.windows.net; początkowa Katalog = [database]; utrzymują informacji security = True; użytkownik id = [user]; password = [hasło]; MultipleActiveResultSets = True; Connection timeout = 30; Max Pool Size = 200; Pooling = true; App = [NazwaAp]

Jak to jest? to możliwe biorąc pod uwagę ograniczenie puli połączeń 200 połączeń?

ps: nie ma okresowego zadania, długotrwałe zapytanie lub inne narzędzie robiące wszystko, sprawdziliśmy przy pomocy sp_who2 wszystkich aktywnych połączeń z bazą danych.

+0

Witam, czy masz wiedzę o aplikacji działającą w sql, czy to zapewnia tę samą analizę wykresu lub pokazuje wszystkie wyjątki jako zależne od poziomu planu usługi istnieje ograniczenie liczby aktywnych równoczesnych połączeń, znalazłem to podczas testu obciążenia . –

+0

Nie rozumiem tego: "Podczas gdy liczba połączonych połączeń utrzymuje się poniżej 200, widzimy, że aktywne połączenia osiągają połączenia 1,5k-2k" co to znaczy? Czy masz wiele maszyn łączących się z bazą danych? –

+0

@MarkWest Zaktualizowałem swój post i dodałem wykres Azure Portal pokazujący ten sam problem. W tym okresie nie występują żadne wyjątki ani awarie usług zależnych (brak zakleszczeń, brak awarii połączenia). –

Odpowiedz

3

[to jest raczej długi komentarz niż odpowiedzi]

mam kilka hostów podłączonych do tej samej bazy danych, ale każdy host ma takie same ograniczenia 200 połączeń

połączenia Pula jest za (Ciąg połączenia, AppDomain). Każdy serwer może mieć wiele domen aplikacji. Każda aplikacja AppDomain będzie miała jedną pulę połączeń na ciąg połączenia. Jeśli masz różne kombinacje użytkowników i haseł, wygenerują one różne pule połączeń. Więc nie ma prawdziwej tajemnicy, dlaczego możliwe jest posiadanie ponad 200 połączeń.

Dlaczego więc uzyskujesz wiele połączeń? Możliwe przyczyny:

Wycieki połączeń.

Jeśli nie uda się usunąć DbContext lub SqlConnection, połączenie to pozostanie na sterowanej stercie do czasu sfinalizowania i nie będzie dostępne do ponownego użycia. Gdy pula połączeń osiągnie swój limit, nowe żądanie połączenia będzie czekać 30 sekund, aż połączenie stanie się dostępne, a następnie zakończy się niepowodzeniem.

W tym scenariuszu nie będzie żadnych czekania ani blokowania na serwerze. Wszystkie sesje będą bezczynne, a nie czekające.I nie będzie to duża liczba wniosków w

select * 
from sys.dm_exec_requests 

Należy pamiętać, że sesja Czekaj Statystyki są teraz żyć na Azure SQL DB, więc jest dużo łatwiej zobaczyć blokowanie w czasie rzeczywistym i czeka.

select * 
from sys.dm_exec_session_wait_stats 

Blokowanie.

Jeśli zlecenia przychodzące zaczynają być blokowane przez niektóre transakcje, a nowe żądania nadal się rozpoczynają, liczba sesji może wzrosnąć, ponieważ nowe żądania otrzymują nowe sesje, rozpoczynają żądania i zostają zablokowane. Zobaczysz wiele zablokowanych żądań w wolnych zapytaniach.

Jeśli żądania trwały długo, aby zakończyć z powodu dostępności zasobów (procesor, dysk, dziennik), można to zobaczyć. Jest to jednak mało prawdopodobne, ponieważ w tym czasie zużycie DTU jest niskie.

Następnym krokiem jest sprawdzenie, czy te połączenia są aktywne na serwerze, co sugeruje blokowanie lub brak aktywności na serwerze, co sugeruje problem z pulą połączeń.

+0

Korzystam z pojedynczego ciągu połączenia, bez zmian z nazwami aplikacji, użytkownikiem, hasłami itd. Pomnożyłem 200xN gdzie 'N' jest liczbą domen aplikacji korzystających z bazy danych. Niemożliwe, że mam więcej niż 3 domeny aplikacji przy użyciu tego samego ciągu połączenia, więc nie więcej niż 600. Znów, nie próbuję znaleźć wycieku połączenia lub zakleszczenia jako części tego pytania, staram się zrozumieć, jak mogę przejdź powyżej 2k połączenia (czasami było to 4,5k!) –

+1

Szybka odpowiedź: Paralelizm – JVC

+0

'Connection.OpenAsync()' i 'ExecuteNonQueryAsync()' itp wydaje się zignorować maksymalną właściwość wielkości puli w connectionstring. –

2

Istnieją dwie rzeczy, które można sprawdzić na obiektach dbcontext, aby sprawdzić, czy używasz ich poprawnie i wyrzucić obiekt, aby przywrócić połączenie z pulą połączeń.

Najpierw tworzy się dbcontext z kodu. Sprawdź, czy istnieje instrukcja użycia wokół każdego zakresu tworzenia obiektu dbcontext. Coś jak:

using (var context = new xxxContext()) { 
    ... 
} 

Spowoduje to usunięcie kontekstu, gdy automatycznie wykracza poza zakres.

Po drugie używasz wtrysku zależności, aby wstrzyknąć obiekt dbcontext. Upewnij się, że używasz scoped:

services.AddScoped<xxxContext>(

Następnie DI zajmie się pozbyciem się obiektów kontekstowych.

Następną rzeczą, którą możesz sprawdzić, jest niezakończone transakcje. Sprawdź, czy wszystkie transakcje są w użyciu bloków, więc będą zatwierdzać lub wycofywać, gdy jesteś poza zakresem.