V rámci podzimní série Databázových školení Quest’s Fall Series představil Brent Ozar, Microsoft Certified Master, výukový program na téma „Avoiding deadlocks with Query Tuning“. Program se zaměřil na tři problémy souběžnosti, které se vyskytují na serveru SQL Server, tři způsoby, jak je opravit, a jeden způsob, který se zdá, že je opravuje, ale ve skutečnosti ne.
Problémy se souběžností:zamykání, blokování a uváznutí na serveru SQL Server
Co jsou problémy se souběžností? Stávají se, když se dotazy snaží vyhnout vzájemnému konfliktu u databázových objektů, jako jsou tabulky. Jsou to:
- Zamykání – Dotazy to dělají neustále, aby zabránily ostatním dotazům používat tabulku ve stejnou dobu. Toto je normální operace databáze.
- Blokování – K tomu dochází, když má jeden dotaz normální zámek, ale jiný dotaz se pokouší získat stejný zámek. Druhý dotaz musí čekat tak dlouho, jak je potřeba, než první dotaz uvolní zámek. V závislosti na povaze prvního dotazu může druhý dotaz čekat velmi krátkou nebo velmi dlouhou dobu. Právě dlouhé čekání skutečně ovlivňuje výkon.
- Zablokování – Zablokování nastane, když jeden dotaz převezme zámek, jiný dotaz jiný a pak každý z nich chce získat zámek toho druhého. SQL Server to řeší tak, že jeden z dotazů označí jako oběť a zabije jej, aby se přerušila patová situace. I když jeden z dotazů může pokračovat, má to také vliv na výkon.
Oprava problémů se souběžností
Bez ohledu na to, zda na serveru SQL Server dochází k blokování nebo zablokování, existují způsoby, jak problémy se souběžností vyřešit. Brent představil tyto tři metody a většinu zbývající části sezení strávil zaměřením na tu druhou – opravu špatného kódu.
- Mějte dostatek indexů, aby byly vaše dotazy rychlé, ale ne tolik, aby to zpomalily tím, že dotazy udrží více zámků po delší dobu
- Vylaďte svůj transakční kód tak, aby dotazy procházely tabulkami pokaždé ve stejném předvídatelném pořadí
- Používejte správnou úroveň izolace pro potřeby vaší aplikace
Když skočil do praktické části programu, Brent komentoval použití příkazů NOLOCK pro blokování a zablokování. Varoval, že NOLOCK tyto problémy ve skutečnosti neřeší, protože se spoléhá na „špinavé čtení“ – v podstatě ignoruje zámky řádků jiných dotazů.
Ve své demonstraci pomocí databáze Stack Overflow vytvořil jednoduchý dotaz, který hledal a počítal lidi jménem „Alex“. Poté vytvořil další dotaz, který spustil aktualizaci u lidí, kteří ne jménem Alex – žádné vkládání ani mazání záznamů. Jeden dotaz by neměl mít nic společného s druhým. Ale jejich společné provozování vede k různým výsledkům v počtu lidí jménem Alex. Je to proto, že NOLOCK vám umožňuje vidět data, která nebyla potvrzena, což vede k náhodným výsledkům, které nemůžete předvídat. Děje se to pouze v rámci souběžnosti.
Je jasné, že pro blokování a uváznutí na SQL Serveru je potřeba lepší oprava, která nevede k náhodným a nepředvídatelným výsledkům.
Lepší řešení pro zablokování SQL
Brent pak předvedl, jak opravit zablokování změnou kódu, který jej způsobuje. Jeho první demo ukazovalo jednoduchou situaci zahrnující dva stoly, takže diváci mohli vidět uváznutí ve zpomaleném záběru, zatímco k němu došlo. Vzhledem k tomu, že SQL Server každých 5 sekund vyhledává zablokování a ukončuje dotaz, který je nejjednodušší vrátit zpět, byli jsme schopni vidět, jak se oběť zablokování objevila.
V jednoduché situaci platí nejobecnější rada, a to dotýkat se tabulek při sestavování dotazů pokaždé ve stejném pořadí. To obecně zabrání vzájemnému zablokování dotazů.
A co složitější dotazy? Pro tento scénář Brent použil realističtější situaci, která by mohla snadno nastat na Stack Overflow, kde si dva lidé vzájemně kladou otázky. Protože do obou transakcí jsou zapojeni stejní uživatelé, způsobí to uváznutí.
Zde nestačí procházet každým stolem pokaždé ve stejném pořadí, ale je také nutné minimalizovat počet dotyků každého stolu. Jak vysvětlil Brent, oprava může zahrnovat nějaký ošklivý kód, který způsobí zablokování dotazů, ale alespoň ne uváznutí. V tomto případě je kratší blok trvání, který umožňuje dokončení obou dotazů, lepší než uváznutí, které ukončí jeden z nich.
Nikdo nechce měnit kód ve stovkách dotazů, takže se zaměřte na ty, které se neustále zablokují, odstraňte z transakce všechny zbytečné řádky a nebojte se zablokovat, abyste se vyhnuli uváznutí.