Jesteśmy zajęci testowaniem systemu OLTP, który opracowaliśmy w .NET 4.0 i uruchamiamy SQL Server 2008 R2 z tyłu. System korzysta z kolejek SQL Server Service Broker, które są bardzo wydajne, ale podczas przetwarzania doświadczamy osobliwego trendu.
SQL Server przetwarza żądania z zawrotną prędkością przez 1 minutę, po czym następuje ~ 20 sekund zwiększonej aktywności zapisu na dysku. Poniższy wykres ilustruje problem.
Yellow = Transactions per second
Blue = Total CPU usage
Red = Sqlsrv Disk Write Bytes/s
Green = Sqlsrv Disk Read Bytes/s
Podczas rozwiązywania problemów próbowaliśmy następujące bez znaczącej zmiany we wzorcu:
- Zatrzymano agenta SQL Server.
- Zabito prawie co drugi uruchomiony proces (brak A / V, SSMS, VS, Eksplorator Windows itp.)
- Usunięto wszystkie inne bazy danych.
- Wyłączono wszystkie liczniki konwersacji (nie używamy żadnych wyzwalaczy).
- Odejście od podejścia opartego na kolejce komunikatów do prostego / surowego projektu monitorowania tabeli.
- Zastosowano różne obciążenia od lekkich do ciężkich.
- Naprawiono wszystkie zakleszczenia.
Wygląda na to, że SQL Server może budować swoją pamięć podręczną i zapisywać ją na dysku w określonych odstępach czasowych, ale nie mogę znaleźć niczego online, aby poprzeć tę teorię.
Następnie planuję przenieść rozwiązanie do naszego dedykowanego środowiska testowego, aby sprawdzić, czy mogę odtworzyć problem. Każda pomoc w tym okresie byłaby bardzo mile widziana.
Aktualizacja 1 Zgodnie z życzeniem, wykres zawierający strony kontrolne stron / s , oczekiwaną długość życia strony i niektóre liczniki opóźnień dysku.
Wygląda na to, że punkt kontrolny (jasnoniebieska linia) jest przyczyną zmniejszonej wydajności (żółta linia), którą obserwujemy. ^
Opóźnienie dysku pozostaje względnie stałe podczas przetwarzania, a oczekiwany czas życia strony nie wydaje się mieć zauważalnego wpływu. Dostosowaliśmy również ilość pamięci RAM dostępnej dla programu SQL Server, co również nie miało dużego wpływu. Zmiana modelu odzyskiwania z SIMPLE
na FULL
również nie miała większego znaczenia.
Aktualizacja 2 Zmieniając „Interwał odzyskiwania” w następujący sposób, udało nam się skrócić interwał, w którym występują punkty kontrolne:
EXEC sp_configure 'show advanced options',1
GO
RECONFIGURE
GO
EXEC sp_configure 'recovery interval', '30'
GO
RECONFIGURE
GO
EXEC sp_configure 'show advanced options',0
GO
RECONFIGURE
Nie jestem jednak pewien, czy jest to zła praktyka?
źródło
FULL
lubBULK_LOGGED
, nadal zachowuje się tak, jakby istniała doSIMPLE
momentu wykonania pełnej kopii zapasowej.Odpowiedzi:
Inni wskazywali już na winowajcę: SQL Server gromadzi aktualizacje w pamięci (w puli buforów) i okresowo je opróżnia (w punktach kontrolnych). Dwie sugerowane opcje (-k i interwał punktu kontrolnego) uzupełniają się:
Ale nie odpowiedziałem tylko na niedomówienie, które otrzymałeś od dobrych komentarzy :)
To, co widzisz, jest niestety bardzo typowym zachowaniem przetwarzania w kolejce . Bez względu na to, czy korzystasz z kolejek Service Broker, czy też używasz tabel jako kolejki , system jest bardzo podatny na tego rodzaju zachowanie. Wynika to z faktu, że przetwarzanie oparte na kolejce jest intensywne w zapisie, a nawet większe w porównaniu z przetwarzaniem OLTP. Zarówno operacje podstawowe, jak i usuwane z kolejki są operacjami zapisu i prawie nie ma operacji odczytu. Mówiąc najprościej, przetwarzanie w kolejce wygeneruje najwięcej zapisów (= najwięcej brudnych stron i najwięcej dzienników) w porównaniu do dowolnego innego obciążenia, nawet OLTP (tj. Obciążenia podobnego do TPC-C ).
Co bardzo ważne, zapisy obciążenia kolejki są zgodne ze wzorcem wstawiania / usuwania: każdy wstawiony wiersz jest bardzo szybko usuwany. Jest to ważne, aby odróżnić od wzorca obciążenia tylko wstawianie (ETL). Zasadniczo karmisz zadanie czyszczenia duchów pełnym posiłkiem i możesz z łatwością go wyprzedzić. Zastanów się, co to znaczy:
Tak, to naprawdę oznacza, że możesz skończyć pisanie strony trzy razy na dysk, w trzech różnych żądaniach We / Wy, dla każdej przetwarzanej wiadomości (najgorszy przypadek). Oznacza to również, że losowe we / wy punktów kontrolnych będą naprawdę losowe, ponieważ punkt zapisu strony zostanie ponownie odwiedzony przez te ruchome głowy między dwoma punktami kontrolnymi (w porównaniu z wieloma obciążeniami OLTP zwykle mają tendencję do grupowania zapisów w niektórych „gorących punktach”, nie kolejki ...).
Masz więc te trzy punkty zapisu, ścigając się, aby wielokrotnie oznaczać tę samą stronę jako brudną. I to przed rozważeniem jakichkolwiek podziałów stron, które mogą być również podatne na przetwarzanie kolejki ze względu na kolejność klawiszy wstawiania. Dla porównania, „typowe” obciążenia OLTP mają znacznie bardziej zrównoważony stosunek odczytu / zapisu, a zapisy OLTP dzielą się na wstawki / aktualizacje / usunięcia, często ze zmianami (zmiany „statusu”) i wstawki, które mają lwia część. Zapisy przetwarzania kolejki są wyłącznie wstawiane / usuwane, z definicji podzielone 50/50.
Oto niektóre konsekwencje:
Moja rekomendacja składa się z 3 liter: S, S i D. Przenieś swój MDF do pamięci, która może obsłużyć szybkie losowe operacje wejścia / wyjścia. SSD. Fusion-IO, jeśli masz pieniądze. Niestety jest to jeden z tych symptomów, których nie można rozwiązać za pomocą taniej pamięci RAM ...
Edytować:
Jak wskazuje Mark, masz dwa dyski logiczne zabezpieczone jednym dyskiem fizycznym. Być może próbowałeś postępować zgodnie z najlepszymi praktykami i podzielić dziennik na D: i dane na C: ale niestety bezskutecznie, C i D to ten sam dysk. Pomiędzy punktami kontrolnymi osiągana jest przepływność sekwencyjna, ale gdy tylko punkt kontrolny się uruchamia, głowice dysków zaczynają się przesuwać, a przepustowość dziennika zapada się, zmniejszając przepustowość całej aplikacji. Upewnij się, że oddzieliłeś dziennik DB, aby dane nie wpłynęły na operacje we / wy danych (osobny dysk).
źródło
C:
iD:
dyski logiczne poparte tym samym dysku fizycznym. Wątpię, czy dysk fizyczny to bateria 100 krótkich wrzecion pasiastych, więc prawdopodobnie jest to główna przyczyna.