sql >> Database teknologi >  >> RDS >> Database

Knee-Jerk Vent-statistikker:SOS_SCHEDULER_YIELD

I mit tidligere indlæg diskuterede jeg LCK_M_XX, ASYNC_NETWORK_IO og OLEDB-venter og de knæfaldende reaktioner på dem. I dette indlæg vil jeg fortsætte med ventestatistik-temaet og diskutere SOS_SCHEDULER_YIELD-venten.

Når SOS_SCHEDULER_YIELD er det mest udbredte på en server, er det almindeligt at se vedvarende, høj CPU-brug. Det knæfaldende reaktion her er, at serveren skal være under CPU-tryk, eller at en spinlock er problemet.

Vi har brug for lidt baggrund her for at forstå disse to reaktioner.

Trådplanlægning

Trådplanlægning i SQL Server administreres af SQL Server selv, ikke af Windows (dvs. det er ikke forebyggende). SQL OS-delen af ​​Storage Engine giver planlægningsfunktionalitet og tråde går fra at køre på en processor (hvor trådtilstanden KØRER) til at være på tjenerlisten og venter på, at en ressource bliver tilgængelig (tilstanden er SUSPENDERET) til at være på den Runnable Sæt i kø, når ressourcen bliver tilgængelig (tilstanden er KØRBAR), og venter på at komme til toppen af ​​køen og tilbage på processoren igen (tilbage til tilstanden, der kører). Jeg har brugt processor, tjenerliste og kø, der kan køres med store bogstaver for at identificere dem som dele af en planlægger.

Når en tråd har brug for en ressource, som den ikke umiddelbart kan erhverve, bliver den suspenderet og venter på tjenerlisten for at blive fortalt (signaleret), at dens ressource er tilgængelig. Den tid, der bruges på tjenerlisten, er ressourceventetiden, og den tid, der bruges på den kørebare kø, er signalventetiden. Tilsammen udgør de den samlede ventetid. SQL OS holder styr på ventetiden og signalets ventetid, så vi er nødt til at lave noget matematik på outputtet fra sys.dm_os_wait_stats for at udlede ressourceventetiden (se mit script her).

Tjenerlisten er uordnet (en hvilken som helst tråd på den kan signaleres til enhver tid og flyttes til køen, der kan køres), og køen, der kan køres, er først-ind-først-ud (FIFO) næsten 100 % af tiden. Den eneste undtagelse fra Runnable Queue er FIFO, hvor der er konfigureret flere Resource Governor-arbejdsbelastningsgrupper i den samme ressourcepulje, og de har forskellige prioriteter i forhold til hinanden. Jeg har aldrig set dette brugt med succes i produktionen, så jeg vil ikke diskutere det yderligere.

Der er en anden grund til, at en tråd muligvis skal flyttes fra processoren - den udtømmer sit kvantum. Trådkvanten i SQL OS er fastsat til 4 millisekunder. Tråden selv er ansvarlig for at fastslå, at dens kvante er opbrugt (ved at kalde hjælperrutiner i SQL OS) og frivilligt opgive processoren (kendt som yielding). Når dette sker, flytter tråden sig direkte til bunden af ​​køen, der kan køres, da den ikke har noget at vente på. SQL OS skal dog registrere en ventetype for denne overgang fra processoren og registrerer SOS_SCHEDULER_YIELD.

Denne adfærd forveksles ofte med CPU-tryk, men det er den ikke - det er bare vedvarende CPU-brug. CPU-tryk og genkendelse af det er et helt andet emne for et fremtidigt indlæg. For så vidt angår dette indlæg, så længe den gennemsnitlige ventetid på signalet er lav (0-0,1-0,2 ms), er det et ret sikkert bud, at CPU-trykket ikke er et problem.

Spinlocks

En spinlock er en synkroniseringsprimitiv på meget lavt niveau, der bruges til at give trådsikker adgang til datastrukturer i SQL Server, der er ekstremt varme (meget flygtige og tilgås og ændres utroligt hyppigt af flere tråde). Eksempler på sådanne strukturer er bufferfrilisten i hver del af bufferpuljen og proportional-fill-vægtningsarrayet for datafilerne i en filgruppe.

Når en tråd skal erhverve en spinlock, ser den ud for at se, om spinlocken er fri, og hvis det er tilfældet straks erhverver den (ved hjælp af en sammenlåst assembly-sprog primitiv som 'test bit clear and set'). Hvis spinlocken ikke kan erhverves, forsøger tråden straks at erhverve den igen, og igen og igen, i op til tusinde iterationer, indtil den går tilbage (sover lidt). Dette registreres ikke som nogen ventetype, da tråden blot kalder Windows sleep()-funktionen, men kan få andre tråde, der venter, til at have store (10-20ms+) signal-ventetider, da den sovende tråd forbliver på processoren, indtil den får spinlock.

Hvorfor taler jeg om spinlocks? Fordi de også kan være en årsag til højt CPU-forbrug, og der er en misforståelse om, at spinlocks er en årsag til SOS_SCHEDULER_YIELD-venter. Det er de ikke.

SOS_SCHEDULER_YIELD Årsager

Så der er én årsag til SOS_SCHEDULER_YIELD:en tråd, der opbruger sit planlægningskvante og stærkt tilbagevendende tilfælde, kan føre til, at SOS_SCHEDULER_YIELD er den mest udbredte ventetid sammen med højt CPU-forbrug.

Du vil ikke se SOS_SCHEDULER_YIELD ventetider dukke op i outputtet fra sys.dm_os_waiting_tasks, da tråden ikke venter. Du kan se, hvilken forespørgsel der genererer SOS_SCHEDULER_YIELD-venterne ved at forespørge på sys.dm_exec_requests og filtrere i kolonnen last_wait_type.

Dette betyder også, at når du ser SOS_SCHEDULER_YIELD i outputtet af sys.dm_os_wait_stats, vil ressourceventen være nul, fordi den faktisk ikke ventede. Men husk, at hver af disse 'venter' svarer til 4ms CPU-tid, der er påløbet for forespørgslen.

Den eneste måde at bevise, hvad der forårsager SOS_SCHEDULER_YIELD-venter, er at fange SQL Server-opkaldsstakke, når denne ventetype forekommer, ved hjælp af udvidede hændelser og fejlfindingssymboler fra Microsoft. Jeg har et blogindlæg, der beskriver og viser, hvordan man udfører denne undersøgelse, og der er et fantastisk whitepaper om spinlocks og spinlock-undersøgelser, som er værd at læse, hvis du er interesseret i den dybde af indre.

I tilfælde af kvanteudmattelse er det ikke grundårsagen. Det er et yderligere symptom. Nu skal vi overveje, hvorfor en tråd kan udtømme sit kvantum gentagne gange.

En tråd kan kun udtømme sit kvante, når den kan fortsætte med at behandle SQL Server-kode i 4ms uden at have brug for en ressource, som en anden tråd ejer – ingen ventetid på låse, sidelåse, datafilsider, der skal læses fra disk, hukommelsesallokeringer, filvækst, logning , eller de utallige andre ressourcer, som en tråd muligvis har brug for.

Det mest almindelige stykke kode, hvor kvanteudmattelse kan opstå og samle store mængder af SOS_SCHEDULER_YIELD-venter, er at scanne et indeks/tabel, hvor alle de nødvendige datafilsider er i hukommelsen, og der ikke er nogen strid om adgang til disse sider, og så det er det. Jeg opfordrer dig til at kigge efter i forespørgselsplaner, når du ser SOS_SCHEDULER_YIELD som den øverste ventetype – store og/eller gentagne indeks-/tabelscanninger.

Dette betyder ikke, at jeg siger, at store scanninger er dårlige, da det kan være, at den mest effektive måde at behandle din arbejdsbyrde på er gennem en scanning. Men hvis SOS_SCHEDULER_YIELD-venterne er nye og usædvanlige og er forårsaget af store scanninger, bør du undersøge, hvorfor forespørgselsplanerne bruger scanninger. Måske har nogen droppet et kritisk ikke-klynget indeks, eller statistikker er forældede, og så en forkert forespørgselsplan blev valgt, eller måske blev en usædvanlig parameterværdi sendt til en lagret procedure, og forespørgselsplanen kaldte på en scanning eller en kodeændring skete uden understøttende indekstilføjelser.

Oversigt

Ligesom med andre ventetyper er det at forstå præcis, hvad SOS_SCHEDULER_YIELD betyder, nøglen til at forstå, hvordan man fejlfinder det, og om adfærden forventes på grund af den arbejdsbyrde, der behandles.

Hvad angår generel ventestatistik, kan du finde mere information om brugen af ​​dem til fejlfinding af ydeevne i:

  • Min SQLskills blogindlægsserie, der starter med Vent-statistikker, eller fortæl mig venligst, hvor det gør ondt
  • Mine ventetyper og låseklasser bibliotek her
  • Mit Pluralsight online-kursus SQL Server:Fejlfinding af ydeevne ved hjælp af ventestatistik
  • SQL Sentry Performance Advisor

I den næste artikel i serien vil jeg diskutere en anden ventetype, der er en almindelig årsag til knæfaldsreaktioner. Indtil da, god fejlfinding!


  1. Hvordan kan jeg bruge en MySql brugerdefineret variabel i en .NET MySqlCommand?

  2. En Marathon Training App Data Model

  3. Psycopg2 Indsæt i tabel med pladsholdere

  4. Docker venter på, at postgresql kører