Database
 sql >> Baza danych >  >> RDS >> Database

Wprowadzenie do zatrzasków

W niektórych z moich poprzednich artykułów na temat dostrajania wydajności omówiłem wiele typów oczekiwania i sposób, w jaki wskazują one na różne wąskie gardła zasobów. Zaczynam nową serię dotyczącą scenariuszy, w których mechanizm synchronizacji zwany zatrzaskiem jest wąskim gardłem wydajności, a w szczególności zatrzaski niebędące stroną. W tym początkowym poście wyjaśnię, dlaczego zatrzaski są wymagane, czym właściwie są i jak mogą być wąskim gardłem.

Dlaczego zatrzaski są potrzebne?

Podstawową zasadą informatyki jest to, że za każdym razem, gdy w systemie wielowątkowym istnieje struktura danych, struktura danych musi być w jakiś sposób chroniona. Ta ochrona daje następujące warunki:

  1. (Gwarantowane) Struktura danych nie może zostać zmieniona przez wątek, gdy inny wątek ją czyta
  2. (Gwarantowane) Struktura danych nie może być odczytana przez wątek, gdy inny wątek ją zmienia
  3. (Gwarantowane) Struktura danych nie może być zmieniana przez dwa lub więcej wątków jednocześnie
  4. (Opcjonalnie) Zezwól co najmniej dwóm wątkom na jednoczesne odczytywanie struktury danych
  5. (Opcjonalnie) Zezwalaj wątkom na kolejkowanie w kolejności w celu uzyskania dostępu do struktury danych

Można to zrobić na kilka sposobów, w tym:

  • Mechanizm, który pozwala na dostęp do struktury danych tylko jednemu wątkowi na raz. SQL Server implementuje ten mechanizm i nazywa go spinlockiem. Pozwala to na powyższe pozycje #1, #2 i #3.
  • Mechanizm, który pozwala wielu wątkom na jednoczesne odczytywanie struktury danych (tj. mają współdzielony dostęp), pozwala pojedynczemu wątkowi na uzyskanie wyłącznego dostępu do struktury danych (z wyłączeniem wszystkich innych wątków) i implementuje uczciwy sposób ustawiania się w kolejce po dostęp. SQL Server implementuje ten mechanizm i nazywa go zatrzaskiem. Pozwala to na wszystkie pięć powyższych postanowień.

Dlaczego więc SQL Server używa zarówno spinlocków, jak i zatrzasków? Dostęp do niektórych struktur danych jest tak częsty, że zatrzask jest po prostu zbyt kosztowny i zamiast tego stosuje się bardzo lekką blokadę spinlock. Dwa przykłady takich struktur danych to lista wolnych buforów w puli buforów i lista blokad w menedżerze blokad.

Co to jest zatrzask?

Zatrzask to mechanizm synchronizacji, który chroni pojedynczą strukturę danych, a w SQL Server istnieją trzy szerokie typy zatrzasków:

  1. Zatrzask chroni stronę pliku danych podczas jej odczytywania z dysku. Pojawiają się one, gdy PAGEIOLATCH_XX czeka i omówiłem je w tym poście.
  2. Zatrzaski chroniące dostęp do strony pliku danych, która już znajduje się w pamięci (strona 8 KB w puli buforów to tak naprawdę tylko struktura danych). Pojawiają się one, gdy PAGELATCH_XX czeka i omówiłem je w tym poście.
  3. Zatrzaski chroniące niestronicowe struktury danych. Pojawiają się one, gdy czekają LATCH_SH i LATCH_EX.

W tej serii skupimy się na trzecim rodzaju zatrzasków.

Zatrzask sam w sobie jest małą strukturą danych i można o nim myśleć jako o trzech elementach:

  • Opis zasobu (co chroni)
  • Pole stanu wskazujące, w których trybach jest aktualnie utrzymywany zatrzask, ile wątków trzyma zatrzask w tym trybie i czy są jakieś wątki oczekujące (plus inne rzeczy, którymi nie musimy się zajmować)
  • Kolejka pierwszy-w-pierwszy-wyszła wątków oczekujących na dostęp do struktury danych i trybów dostępu, na które czekają (zwana kolejką oczekujących)

W przypadku zatrzasków innych niż strony ograniczymy się tylko do rozważenia trybów dostępu SH (udział) do odczytu struktury danych i EX (wyłącznie) do zmiany struktury danych. Istnieją inne, bardziej egzotyczne tryby, ale są one rzadko używane i nie pojawią się jako punkty sporne, więc do końca tej dyskusji będę udawał, że nie istnieją.

Niektórzy z was mogą wiedzieć, że istnieją również głębsze komplikacje związane z superzatrzaskami/podzatrzaskami i partycjonowaniem zatrzasków w celu zapewnienia skalowalności, ale nie musimy zagłębiać się w tę głębię na potrzeby tej serii.

Zdobywanie zatrzasku

Kiedy wątek chce uzyskać zatrzask, sprawdza stan zatrzasku.

Jeśli wątek chce uzyskać zatrzask w trybie EX, może to zrobić tylko wtedy, gdy nie ma wątków trzymających zatrzask w dowolnym trybie. Jeśli tak jest, wątek uzyskuje zatrzask w trybie EX i ustawia status, aby to wskazać. Jeśli istnieje jeden lub więcej wątków już trzymających zatrzask, wątek ustawia stan wskazujący, że istnieje wątek oczekujący, wchodzi na sam dół kolejki oczekiwania, a następnie zostaje zawieszony (na liście kelnerów harmonogramu, w którym się znajduje ) czeka na LATCH_EX.

Jeśli wątek chce uzyskać zatrzask w trybie SH, może to zrobić tylko wtedy, gdy żaden wątek nie trzyma zatrzasku lub jedyne wątki trzymające zatrzask są w trybie SH * i * nie ma wątków oczekujących na uzyskanie zatrzasku. W takim przypadku wątek uzyskuje zatrzask w trybie SH, ustawia stan wskazujący na to i zwiększa liczbę wątków trzymających zatrzask. Jeśli zatrzask jest utrzymywany w trybie EX lub istnieje jeden lub więcej oczekujących wątków, wątek ustawia stan wskazujący, że istnieje oczekujący wątek, wchodzi na sam dół kolejki oczekującej, a następnie zostaje zawieszony w oczekiwaniu na LATCH_SH.

Sprawdzanie oczekujących wątków jest wykonywane, aby zapewnić uczciwość wątku oczekującego na zatrzask w trybie EX. Będzie musiał tylko czekać na wątki trzymające zatrzask w trybie SH, które uzyskały zatrzask, zanim zacznie czekać. Bez tej kontroli może wystąpić termin informatyczny zwany „głodzeniem”, gdy stały strumień wątków pobierających zatrzask w trybie SH uniemożliwia wątkowi trybu EX uzyskanie zatrzasku.

Zwalnianie zatrzasku

Jeśli wątek przytrzymuje zatrzask w trybie EX, wyłącza stan pokazujący, że zatrzask jest utrzymywany w trybie EX, a następnie sprawdza, czy są jakieś oczekujące wątki.

Jeśli wątek przytrzymuje zatrzask w trybie SH, zmniejsza liczbę wątków trybu SH. Jeśli liczba jest teraz niezerowa, wątek zwalniający jest wykonywany z zatrzaskiem. Jeśli liczba *wynosi* teraz zero, wyłącza stan pokazujący, że zatrzask jest utrzymywany w trybie SH, a następnie sprawdza, czy są jakieś oczekujące wątki.

Jeśli nie ma żadnych oczekujących wątków, zwalnianie wątku odbywa się za pomocą zatrzasku.

Jeśli nagłówek oczekującej kolejki czeka na tryb EX, wątek zwalniający wykonuje następujące czynności:

  • Ustawia status pokazujący, że zatrzask jest utrzymywany w trybie EX
  • Usuwa oczekujący wątek z początku kolejki i ustawia go jako właściciela zatrzasku
  • Symuluje oczekujący wątek, że jest właścicielem i że można go teraz uruchomić (poprzez przeniesienie oczekującego wątku z listy oczekujących w harmonogramie do uruchamialnej kolejki w harmonogramie)
  • I gotowe za pomocą zatrzasku

Jeśli nagłówek oczekującej kolejki czeka w trybie SH (co może mieć miejsce tylko wtedy, gdy wątek zwalniający był w trybie EX), wątek zwalniający wykonuje następujące czynności:

  • Ustawia status pokazujący, że zatrzask jest utrzymywany w trybie SH
  • Dla wszystkich wątków w kolejce oczekujących na tryb SH
    • Usuwa oczekujący wątek z początku kolejki
    • Zwiększa liczbę wątków trzymających zatrzask
    • Symuluje oczekujący wątek, że jest właścicielem i można go teraz uruchomić
  • I gotowe za pomocą zatrzasku

Jak zatrzaski mogą być punktem spornym?

W przeciwieństwie do zamków, zatrzaski są zwykle utrzymywane tylko na czas operacji odczytu lub zmiany, więc są dość lekkie, ale z powodu niezgodności SH vs. EX mogą być tak samo dużym punktem spornym jak blokady. Może się to zdarzyć, gdy wiele wątków próbuje uzyskać zatrzask w trybie EX (tylko jeden na raz może) lub gdy wiele wątków próbuje uzyskać zatrzask w trybie SH, a inny wątek trzyma zatrzask w trybie EX.

Podsumowanie

Im więcej wątków w systemie rywalizuje o „gorący” zatrzask, tym większa rywalizacja i tym bardziej negatywny wpływ na przepustowość obciążenia. Prawdopodobnie słyszałeś o dobrze znanych problemach z rywalizacją o zatrzaski, na przykład wokół map bitowych alokacji tempdb, ale rywalizacja może również wystąpić w przypadku zatrzasków innych niż strony.

Teraz mam wystarczająco dużo informacji, aby zrozumieć zatrzaski i sposób ich działania. W kilku następnych artykułach przeanalizuję niektóre rzeczywiste problemy z rywalizacją o zatrzaski niebędące stroną strony i wyjaśnię, jak im zapobiegać lub jak je obejść.


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Jak przechowywać harmonogramy pracowników w bazie danych

  2. Plany wydobywcze:nie tylko dla pamięci podręcznej planów

  3. Zgrupowane łączenie:zamawianie i usuwanie duplikatów

  4. Jak zacząć korzystać z Amazon ECS i Amazon Fargate?

  5. Routing tylko do odczytu dla zawsze włączonych