sql >> Databáze >  >> RDS >> Database

Sledování vysokého čekání CLR_MANUAL_EVENT

Nedávno jsem od někoho z komunity obdržel e-mailovou otázku týkající se CLR_MANUAL_EVENT typ čekání; konkrétně, jak řešit problémy s tímto čekáním, které se náhle stalo převládajícím pro existující pracovní zátěž, která se silně spoléhala na typy prostorových dat a dotazy pomocí prostorových metod na serveru SQL Server.

Moje první otázka jako konzultanta je téměř vždy:"Co se změnilo?" Ale v tomto případě, stejně jako v mnoha případech, jsem byl ujištěn, že se nic nezměnilo s kódem aplikace nebo vzorci pracovní zátěže. Takže mojí první zastávkou bylo vytáhnout CLR_MANUAL_EVENT počkejte v knihovně typů čekání SQLskills.com, abyste viděli, jaké další informace jsme již shromáždili o tomto typu čekání, protože se běžně nejedná o čekání, se kterým na serveru SQL Server vidím problémy. Co mě opravdu zaujalo, byl graf/teplotní mapa výskytů pro tento typ čekání poskytnutá SentryOne v horní části stránky:

Skutečnost, že pro tento typ nebyla shromážděna žádná data v celém dobrém průřezu jejich zákazníků, mi skutečně potvrdila, že se nejedná o něco, co by bylo běžně problémem, takže mě zaujala skutečnost, že tato specifická pracovní zátěž se nyní projevovala problémy s tímto čekáním. Nebyl jsem si jistý, kam jít, abych problém dále prošetřil, a tak jsem na e-mail odpověděl, že se omlouvám, že nemohu dále pomoci, protože nemám ponětí, co by způsobilo doslova desítky vláken provádějících prostorové dotazy. najednou začněte muset čekat 2-4 sekundy najednou na tento typ čekání.

O den později jsem od osoby, která položila otázku, obdržel laskavý následný e-mail, který mě informoval, že problém vyřešili. Ve skutečnosti se nic ve skutečné zátěži aplikace nezměnilo, ale došlo ke změně prostředí. Na všechny servery v jejich infrastruktuře byl jejich bezpečnostním týmem nainstalován softwarový balíček třetí strany a tento software shromažďoval data v pětiminutových intervalech a způsoboval, že zpracování .NET garbage collection běželo neuvěřitelně agresivně a „zbláznilo se“. říkali. Vyzbrojen těmito informacemi a některými svými dřívějšími znalostmi o vývoji .NET jsem se rozhodl, že si s tím chci trochu pohrát a zjistit, zda dokážu toto chování reprodukovat a jak bychom mohli dále řešit příčiny.

Základní informace

V průběhu let jsem vždy sledoval blog PSSQL na MSDN, a to je obvykle jedno z mých míst, kam chodím, když si vzpomenu, že jsem někdy v minulosti četl o problému souvisejícím se serverem SQL, ale nemohu. nepamatuji si všechna specifika.

Na blogu je příspěvek s názvem Vysoká čekání na CLR_MANUAL_EVENT a CLR_AUTO_EVENT Jack Li z roku 2008, který vysvětluje, proč lze tato čekání bezpečně ignorovat v souhrnu sys.dm_os_wait_stats DMV, protože k čekání dochází za normálních podmínek, ale neřeší, co dělat, pokud jsou čekací doby příliš dlouhé, nebo co by mohlo způsobit, že jsou vidět ve více vláknech v sys.dm_os_waiting_tasks aktivně.

Existuje další blogový příspěvek od Jacka Li z roku 2013 s názvem Problém s výkonem zahrnující CLR garbage collection a nastavení afinity SQL CPU na kterou odkazuji v naší třídě ladění výkonu IEPTO2, když mluvím o úvahách o více instancích a o tom, jak může .NET Garbage Collector (GC) spouštěný jednou instancí ovlivnit ostatní instance na stejném serveru.

GC v .NET existuje, aby snížilo využití paměti aplikacemi používajícími CLR tím, že umožňuje automatické čištění paměti přidělené objektům, čímž se eliminuje potřeba, aby vývojáři museli ručně zpracovávat alokaci paměti a dealokaci v míře požadované nespravovaným kódem. . Funkce GC je zdokumentována v Books Online, pokud byste se chtěli dozvědět více o tom, jak funguje, ale specifika kromě skutečnosti, že sbírky mohou být blokovány, nejsou pro řešení problémů s aktivním čekáním na CLR_MANUAL_EVENT důležitá. v SQL Server dále.

Jak se dostat ke kořenu problému

S vědomím, že problém byl způsoben shromažďováním odpadků pomocí .NET, jsem se rozhodl provést určité experimenty pomocí jediného prostorového dotazu proti AdventureWorks2016 a velmi jednoduchý skript PowerShell pro ruční vyvolání garbage collectoru ve smyčce pro sledování toho, co se děje v sys.dm_os_waiting_tasks uvnitř SQL Serveru pro dotaz:

USE AdventureWorks2016;
GO  
SELECT a.SpatialLocation.ToString(), a.City, b.SpatialLocation.ToString(), b.City
  FROM Person.Address AS a
  INNER JOIN Person.Address AS b ON a.SpatialLocation.STDistance(b.SpatialLocation) <= 100 
  ORDER BY a.SpatialLocation.STDistance(b.SpatialLocation); 

Tento dotaz porovnává všechny adresy v Person.Address tabulky proti sobě, abyste našli jakoukoli adresu, která je do 100 metrů od jakékoli jiné adresy v tabulce. To vytváří dlouhotrvající paralelní úlohu uvnitř SQL Server, která také vytváří velký kartézský výsledek. Pokud se rozhodnete toto chování reprodukovat sami, neočekávejte, že to dokončí nebo vrátí výsledky zpět. Se spuštěným dotazem začne nadřazené vlákno pro úlohu čekat na CXPACKET čeká a dotaz pokračuje ve zpracování několik minut. Co mě však zajímalo, bylo to, co se stane, když dojde ke shromažďování odpadků v běhovém prostředí CLR nebo pokud je vyvoláno GC, takže jsem použil jednoduchý skript PowerShell, který by zacyklil a ručně vynutil spuštění GC.

POZNÁMKA:TOTO NENÍ DOPORUČENÝ PRAXE VE VÝROBNÍM KÓDU Z MNOHA DŮVODŮ!

while (1 -eq 1) {[System.GC]::Collect() }

Jakmile bylo spuštěno okno PowerShellu, téměř okamžitě se mi začalo zobrazovat CLR_MANUAL_EVENT čekání vyskytující se u paralelních dílčích úloh (uvedených níže, kde exec_context_id je větší než nula) v sys.dm_os_waiting_tasks :

Nyní, když jsem mohl spustit toto chování a začalo být jasné, že SQL Server zde nemusí nutně znamenat problém a může být jen obětí jiné aktivity, chtěl jsem vědět, jak se ponořit hlouběji a určit hlavní příčinu problému. . Zde se PerfMon hodil pro sledování skupiny čítačů paměti .NET CLR pro všechny úlohy na serveru.

Tento snímek obrazovky byl zmenšen, aby zobrazoval kolekce pro sqlservr a powershell jako aplikace ve srovnání s _Global_ kolekce pomocí běhového prostředí .NET. Vynucení GC.Collect() pro neustálé spuštění vidíme, že powershell instance řídí kolekce GC na serveru. Pomocí této skupiny čítačů PerfMon můžeme sledovat, které aplikace provádějí nejvíce kolekcí, a odtud pokračovat v dalším zkoumání problému. V tomto případě jednoduché zastavení skriptu PowerShell eliminuje CLR_MANUAL_EVENT čeká uvnitř SQL Serveru a dotaz pokračuje ve zpracování, dokud jej nezastavíme nebo mu neumožníme vrátit miliardu řádků výsledků, které by z něj vyšly.

Závěr

Pokud máte aktivní čekání na CLR_MANUAL_EVENT způsobuje zpomalení aplikace, nepředpokládejte automaticky, že problém existuje uvnitř SQL Serveru. SQL Server používá úklid na úrovni serveru (alespoň před SQL Server 2017 CU4, kde malé servery s méně než 2 GB RAM mohou používat úklid na úrovni klienta ke snížení využití prostředků). Pokud k tomuto problému dochází na serveru SQL Server, použijte skupinu čítačů paměti .NET CLR v PerfMon a zkontrolujte, zda jiná aplikace neřídí úklid v CLR a v důsledku toho interně blokuje úkoly CLR na serveru SQL.


  1. SQL Server podmíněný tok

  2. Datový typ záznamu založený na kurzoru s kurzorem vracejícím více hodnot v databázi Oracle

  3. Získejte sadu výsledků z uložené procedury Oracle

  4. ORA-00838