SQL Server DB staje się bezużyteczny z dnia na dzień

9

Wczoraj moja baza danych SQL Server była w porządku. Dziś jest prawie bezużyteczny - spowalnia go od pięciu do dwudziestu, w zależności od tego, kiedy go uderzyłem.

Niektóre dane zostały dodane do serwera podczas procesu ładowania z dnia na dzień, ale nic tak jak wolumin, który powinien mieć tak duży wpływ na bazę danych. Około 50 000 rekordów w postaci zwykłego tekstu (bez XML lub innych drobiazgów).

Serwer został załatany dziś rano, zanim go ponownie uruchomiliśmy. Jednak żaden z naszych innych serwerów baz danych, które również zostały załatane, nie zachowuje się inaczej.

Wydaje się, że Monitor zasobów sugeruje, że wadliwe jest jego IO dysku. Cały czas działa na prawie 100% pojemności pliku .mdf, nawet jeśli w bazie danych niewiele się dzieje. Dostęp do Templog.ldf również działa dość wysoko.

Nikt tutaj nie jest ekspertem DBA (wszyscy jesteśmy programistami z różną liczbą umiejętności SQL) i wszyscy jesteśmy zaskoczeni tym, co się stało. Próbowaliśmy uruchomić sp_updatestats i przenieść niektóre duże indeksy na różne dyski, ale bezskutecznie.

Myślę, że to musi mieć coś wspólnego z łatką - wydaje się to zbyt częstym przypadkiem. Kolega jest przekonany, że to obciążenie danych spowodowało wzrost wielkości pliku mdf do punktu, w którym spowodowało to, że plany wykonania stały się nieefektywne.

Co do cholery to spowodowało? Jak możemy się dowiedzieć i co możemy zrobić, aby to naprawić?

EDYTOWAĆ:

Używanie sp_WhoIsActivenie ujawnia niczego niezwykłego. Rejestruje moje własne użycie sproc i niektóre polecenia od kolegi, który obecnie próbuje przenieść inny indeks. To prawdopodobnie trzyma teraz DB, ale wcześniej działało tak samo źle.

Jest to standardowa wersja SQL Server 2008 R2. SELECT @@VERSIONdaje:

Microsoft SQL Server 2008 R2 (SP2) - 10.50.4033.0 (X64)
9 lipca 2014 16:04:25
Prawa autorskie (c) Microsoft Corporation Standard Edition (64-bit) na Windows NT 6.1 (Build 7601: Service Pack 1) (Hypervisor )

Serwer ma 72 GB pamięci RAM i trzy czterordzeniowe procesory 2 GHz.

Łatka została zastosowana tylko do systemu Windows. Nie wprowadzono żadnych zmian poza łatką.

Wybrane ustawienia:

_id     name                        value   minimum     maximum     value_in_use    description                                 is_dynamic  is_advanced
1540    min memory per query (KB)   1024    512         2147483647  1024            minimum memory per query (kBytes)           1           1
1541    query wait (s)              -1      -1          2147483647  -1              maximum time to wait for query memory (s)   1           1
1543    min server memory (MB)      0       0           2147483647  16              Minimum size of server memory (MB)          1           1
1544    max server memory (MB)      65536   16          2147483647  65536           Maximum size of server memory (MB)          1           1

AKTUALIZACJA: Przenoszenie indeksów i tabel do różnych partycji dysku wydaje się poprawiać. Nadal jestem zdezorientowany, jak mogliśmy tak nagle osiągnąć punkt krytyczny z tak drastycznymi skutkami.

Bob Tway
źródło
Czy możesz uruchomić sp_whoisactive przez 5 minut i przechwycić dane wyjściowe do tabeli. Możesz pobrać go stąd, a to pokaże, jak możesz przechwycić dane wyjściowe do tabeli
Kin Shah
Cóż, jeśli zrestartowałeś serwer, oznacza to, że wszystkie twoje buforowane dane zostały zrzucone z puli buforów, a także wszystkie twoje buforowane plany wykonania zostały również zrzucone. Oznacza to, że SQL Server będzie musiał przyspieszyć oba - każdy plan wykonania będzie musiał zostać ponownie skompilowany, a jeśli statystyki będą nieaktualne, możesz nie uzyskać najbardziej wydajnych planów. Oznacza to również, że dane będą musiały zostać wczytane do pamięci z dysku, podczas gdy przed ponownym uruchomieniem prawdopodobnie buczało wraz z danymi w pamięci. To powinno być krótkotrwałe.
Aaron Bertrand
@AaronBertrand Tak było przez osiem godzin. Regularnie restartujemy serwer w celu łatania i nigdy wcześniej nie zauważyliśmy czegoś takiego.
Bob Tway
1
Nie używaj interfejsu użytkownika do sprawdzania ustawień konfiguracji. SELECT * FROM sys.configurations;- chcesz value, value_in_usetakich rzeczy jak max server memory (MB). Przydałby się również numer kompilacji SELECT @@VERSION;, a także to, czy znajduje się on w hiperwizorze i czy cokolwiek zmieniło się na hoście od wczoraj (lub od ostatniego uruchomienia SQL Server).
Aaron Bertrand
2
Jakiego typu podsystemu IO używasz? SAN, dysk lokalny itp.? Czy jest jakaś szansa, że ​​przypadkiem masz dysk zepsuty? Czy któreś z Twoich baz danych są przechowywane w tej samej lokalizacji, co pliki systemu operacyjnego? I ostatnie pytanie. Częścią naszego procesu przed aktualizacją systemu operacyjnego było wcześniejsze wykonanie migawki maszyny wirtualnej. Niestety osoba odpowiedzialna zapomniała go popełnić. Bardzo szybko cały system stał się coraz wolniejszy. Czy jest jakaś szansa, że ​​ci się to przydarzyło?
Kenneth Fisher

Odpowiedzi:

3

Może się zdarzyć, że niewielka ilość danych osiągnie określony limit w SQL Server, aby wymusić inny plan lub coś w tym rodzaju. To nie jest mało prawdopodobne. Ale fakt, że twoja płyta wydaje się być na służbie, prowadzi mnie do innego wniosku.

Istnieją dwa możliwe podstawowe powody spowolnienia.

  1. Zaktualizowałeś system i uruchomiłeś go ponownie
  2. Ładujesz w nim wiązkę danych

Rzućmy okiem na część nr 1

Możliwe, że konfiguracja programu SQL Server może być zepsuta. Może to powodować poważne problemy dotyczące szybkości serwera i użycia dysku.

Najpierw sprawdź swoje podstawowe ustawienia serwera. Te podstawowe ustawienia max server memory, affinity I/O mask, affinity maski max degree of parallelism. Może być konieczne włączenie opcji zaawansowanych za pomocą show advanced options.

Oto kompletny skrypt:

-- enable advanced options
EXEC sp_configure 'show advanced options',1
-- apply configuration
RECONFIGURE
-- how much memory can the sql server allocate?
EXEC sp_configure 'max server memory'
-- which cpu is used to run I/O operations
EXEC sp_configure 'affinity I/O mask'
-- which cpus can run processes?
EXEC sp_configure 'affinity mask'
-- how many threads can work on one query part?
EXEC sp_configure 'max degree of parallelism'

Porównaj wynik z udokumentowanymi wartościami w krokach instalacji. Czy nadal są takie same?

Może to mieć wiele powodów, dla których twój serwer zachowuje się tak dziwnie. Normalnie założę się, że max server memorypo prostu się mylisz. Spowoduje to, że Twój SQL Server na stałe zmieni strony danych. Nie może zatrzymać wszystkiego w swojej pamięci. Oznacza to, że musi odczytać strony z dysku, zaktualizować go, natychmiast zapisać. Jeśli pojawi się kolejna aktualizacja, która używa tej samej strony do aktualizacji, nie można jej odczytać z pamięci. Zamiast tego serwer musi odczytać go ponownie z dysku. Po prostu zamiana ...

Innym problemem może być zbyt duże powinowactwo do dysku lub procesów. Jeśli korzystałeś ze wspólnego serwera (SQL Server + inne usługi) z dedykowaną płytą dla SQL Server (co może być rzadkim przypadkiem, ale może być), może to być twój problem. Twój serwer zwykle miał na przykład 3 procesory dla procesów i jeden dla I / O. Pozostałe 12 procesorów jest wykorzystywane do innych usług. W takim przypadku maska ​​koligacji jest nieprawidłowa i używa na przykład automatycznej konfiguracji. Oznacza to, że Twój serwer używa dynamicznie wszystkich 16 rdzeni do procesów i operacji we / wy. Jeśli masz uruchomione ogromne procesy, mogą one spowodować ogromne obciążenie dysku, którego może nie obsłużyć. Ale tak naprawdę nie wierzę, że to twoja sprawa. Byłoby to szybsze (choćby odrobinę), gdyby tak się stało, ale twoja sprawa jest wolniejsza.

Kolejnym problemem może być zbyt wysoki stopień równoległości. Co oznacza, że ​​masz zbyt wiele wątków na biegu jałowym w jednej części zapytania. Może to również spowodować ogromne spowolnienie, jeśli równoległość nie będzie działać zgodnie z oczekiwaniami. Ale to nie opisuje w ogóle twojego wysokiego I / O.

Teraz spójrzmy również na część nr 2

Ładujesz kilka wierszy do swojego systemu. Nawet jeśli jest to zwykłe zadanie, może zwiększyć limit, w którym eskalują się twoje plany zapytań. Może być nawet tak, że wstawianie w połączeniu z SQL Server powoduje takie zachowanie.

Wspomniałeś, że już próbowałeś przenieść swoje indeksy na inną płytę, co wydaje się pomóc. Może się tak zdarzyć tylko dlatego, że podzieliłeś obciążenie na dwie różne płyty.

Może się zdarzyć, że Twoje wskaźniki zostały złamane, Twoje plany zostały złamane lub że Twoje statystyki są po prostu nieaktualne.

1. pozwala sprawdzić statystyki ostatniej aktualizacji Możesz to zrobić ręcznie przez interfejs dla każdego pojedynczego elementu statystyki. Co byłoby bólem. Lub możesz wypróbować ten kod:

SELECT name AS indexname,
STATS_DATE(OBJECT_ID, index_id) AS StatsUpdated
FROM sys.indexes

To da ci pełną informację o każdym indeksie (i sterty) i statystykach za nimi. Nawet jeśli uruchomisz sp_updatestats, nie oznacza to, że statystyki zostały zaktualizowane. Część, w której aktualizacja jest dość trudna, nawet jeśli uruchomisz sp_updatestatslub nawet jeśli auto update statisticsjest włączona, statystyki nie zostaną zaktualizowane na czas. Oto kilka punktów granicznych, kiedy aktualizacja jest potrzebna / generowana:

  • Pusta tabela otrzymuje jeden lub więcej wierszy
  • Tabela z ponad 500 wierszami aktualizuje 20% + 500 dodatkowych wierszy, a następnie wstawiono wstawkę
  • Gdy 500 wierszy zostało zmienionych w tabeli zawierającej mniej niż 500 wierszy

Oznacza to, że Twoje statystyki mogą być nieaktualne, nawet jeśli uruchomisz aktualizację.

Możesz spojrzeć na powyższe zapytanie. Jeśli znajdziesz jakieś stare statystyki w niektórych tabelach, możesz chcieć uruchomić ręczną aktualizację statystyk dla tej tabeli:

UPDATE STATISTICS dbo.YourBadTable WITH FULLSCAN

Następnie możesz dać serwerowi kopniaka w tyłek, aby odrzucić wszystkie stare plany.

DBCC FREEPROCCACHE 

Jeśli chcesz po prostu wyczyścić wszystkie pamięci podręczne, możesz zamiast tego uruchomić to:

DBCC FREESYSTEMCACHE ('ALL')

Spowoduje to wyczyszczenie wszystkich pamięci podręcznych, a nie tylko pamięci podręcznej planu. Zazwyczaj ostrzegałbym, aby użyć tego na serwerze produkcyjnym w fazie produkcyjnej. Ale ponieważ twój serwer obecnie nie działa, nie możesz za bardzo go skrzywdzić. Może to spowolnić na kilka sekund, może 1-2 minut, ponieważ musi odbudować wszystkie skrzynki, ale potem powinien biegać z odpowiednimi planami.

Innym powodem mogą być całkowicie rozdrobnione wskaźniki. Można to sprawdzić na całym serwerze za pomocą tego oświadczenia:

SELECT * 
FROM sys.dm_db_index_physical_stats (NULL, NULL, NULL, NULL, NULL)

Jeśli fragmentacja jest bardzo wysoka, może być konieczna reorganizacja (fragmentacja <20%) lub całkowite przebudowanie (> 20%). Może to wywierać większy nacisk na płytę i powodować problemy. Z drugiej strony, jeśli indeksy są tak złe, prawdopodobnie ostatecznie pomogłoby bardziej niż szkodzi.

Oprócz tych dwóch powodów nadal może być trzeci problem

Możliwe, że twój serwer jest skonfigurowany prawdopodobnie, nie zmieniłeś żadnego kodu w tym czasie, po prostu dodałeś kilka wierszy. Wszystkie statystyki są aktualizowane, a wszystkie pamięci podręczne są odbudowywane. Wszystkie twoje wskaźniki są zreorganizowane w taki sposób, w jaki ich potrzebujesz, ale nadal - nic nie działa. Możliwe, że osiągnąłeś limit dostępnej pamięci w swoich procesach. Może potrzebujesz więcej. Możesz po prostu sprawdzić, czy istnieje proces, który próbuje uzyskać więcej pamięci niż masz.

Możesz to sprawdzić za pomocą tego polecenia:

SELECT * FROM sys.dm_exec_query_memory_grants

Zapewni Ci listę wszystkich sesji zużywających pamięć. Może być jakieś zapytanie, które wciąż czeka na uzyskanie pamięci. Te zapytania można łatwo filtrować. Wszystkie sesje gdzie granted_memory_kb IS NULL. Są to sesje, które żądały pamięci, ale jej nie dostają. Inną rzeczą może być przyznana pamięć, która może być za niska. Możesz porównać kolumny requested_memory_kbz granted_memory_kb. Żądane pokazuje, ile pamięci proces musi optymalnie uruchomić, a przyznane pokazuje pamięć, która jest włączona dla procesu. Jeśli proces wymaga 2 GB do uruchomienia, ale zajmuje tylko 2 MB ... możesz go zdobyć samodzielnie. ;-)

Innym sposobem jest sprawdzenie RESSOURCE_SEMAPHORE:

SELECT * FROM sys.dm_exec_query_resource_semaphore

Możesz rzucić okiem na waiter_counti grantee_count. Jeśli kelner ma wartość większą niż 0, masz presję na pamięć, co może powodować zamianę i ciśnienie dysku widoczne w perfmon.

joński
źródło
0

Oprócz możliwych awarii dysku sprawdź stan podsystemu RAID. Widzieliśmy coś podobnego i okazało się, że bateria kontrolera RAID uległa awarii, więc nie było dostępnej pamięci podręcznej zapisu - wszystkie zapisy musiały przejść bezpośrednio na dysk. Jedna uwaga - mogliśmy poczuć, że system zatrzymuje się podczas RDC.

William Jens
źródło