sql >> Databáze >  >> RDS >> Sqlserver

Anatomie uváznutí SQL Serveru a nejlepší způsoby, jak se jim vyhnout

Databázoví profesionálové se běžně potýkají s problémy s výkonem databáze, jako je nesprávné indexování a špatně napsaný kód v produkčních instancích SQL. Předpokládejme, že jste aktualizovali transakci a SQL Server ohlásil následující zprávu o zablokování. Pro administrátory, kteří právě začínají, to může být šok.

V tomto článku prozkoumáme uváznutí SQL Serveru a nejlepší způsoby, jak se jim vyhnout.

Co je zablokování serveru SQL?

SQL Server je vysoce transakční databáze. Předpokládejme například, že podporujete databázi pro online nákupní portál, kde nepřetržitě přijímáte nové objednávky od zákazníků. Více uživatelů pravděpodobně provádí stejnou činnost ve stejnou dobu. V tomto případě by vaše databáze měla splňovat vlastnosti Atomicita, Konzistence, Izolace, Trvanlivost (ACID), aby byla konzistentní, spolehlivá a chránila integritu dat.

Obrázek níže popisuje vlastnosti ACID v relační databázi.

Chcete-li sledovat vlastnosti ACID, SQL Server používá zamykací mechanismy, omezení a protokolování předem. Mezi různé typy zámků patří:výhradní zámek (X), sdílený zámek (S), aktualizační zámek (U), zámek záměru (I), zámek schématu (SCH) a zámek hromadné aktualizace (BU). Tyto zámky lze získat na úrovni klíče, tabulky, řádku, stránky a databáze.

Předpokládejme, že máte dva uživatele, Jana a Petra, kteří jsou připojeni k databázi zákazníků.

  • Jan chce aktualizovat záznamy pro zákazníka s [customerid] 1.
  • Zároveň chce Petr získat hodnotu pro zákazníka s [customerid] 1.

V tomto případě SQL Server používá následující zámky pro Jana i Petra.

Zámky pro Jana

  • Na tabulce zákazníků a na stránce, která obsahuje záznam, je zapotřebí zámek výhradního záměru (IX).
  • Dále vyžaduje exkluzivní zámek (X) na řádku, který chce John aktualizovat. Zabraňuje jakémukoli jinému uživateli upravovat data řádku, dokud proces A neuvolní svůj zámek.

Zámky pro Petra

  • Získává zámek sdíleného záměru (IS) v tabulce zákazníků a na stránce, která obsahuje záznam podle klauzule where.
  • Pokouší se použít sdílený zámek ke čtení řádku. Tato řada již má exkluzivní zámek pro Johna.

V tomto případě musí Peter počkat, až John dokončí svou práci a uvolní exkluzivní zámek. Tato situace je známá jako blokování.

Nyní předpokládejme v jiném scénáři, že John a Peter mají následující zámky.

  • Jan má exkluzivní zámek na zákaznické tabulce pro zákaznické ID 1.
  • Petr má exkluzivní zámek na tabulce objednávek pro číslo zákazníka 1.
  • Jan vyžaduje k dokončení transakce výhradní zámek na tabulce objednávek. Peter už má na stole objednávek exkluzivní zámek.
  • Petr vyžaduje k dokončení transakce exkluzivní zámek na zákaznickém stole. John už má na zákaznickém stole exkluzivní zámek.

V tomto případě nemůže žádná z transakcí pokračovat, protože každá transakce vyžaduje zdroj držený druhou transakcí. Tato situace je známá jako zablokování serveru SQL.

Mechanismy monitorování zablokování serveru SQL Server

SQL Server pravidelně monitoruje situace zablokování pomocí podprocesu sledování zablokování. To kontroluje procesy zapojené do uváznutí a identifikuje, zda se relace stala obětí zablokování. K identifikaci procesu oběti uváznutí používá vnitřní mechanismus. Ve výchozím nastavení se za oběť považuje transakce s nejmenším množstvím zdrojů požadovaných pro vrácení zpět.

SQL Server ukončí relaci oběti, aby další relace mohla získat požadovaný zámek k dokončení transakce. Ve výchozím nastavení SQL Server kontroluje situaci zablokování každých 5 sekund pomocí monitoru zablokování. Pokud detekuje uváznutí, může snížit frekvenci z 5 sekund na 100 milisekund v závislosti na výskytu uváznutí. Pokud nedojde k častým uváznutím, obnoví to vlákno monitorování na 5 sekund.

Jakmile SQL Server zabije proces jako oběť zablokování, obdržíte následující zprávu. V této relaci byl proces ID 69 obětí uváznutí.

Dopady používání příkazů priority uváznutí na SQL Server

Ve výchozím nastavení SQL Server označí transakci s nejlevnějším vrácením zpět jako oběť uváznutí. Uživatelé mohou nastavit prioritu uváznutí v transakci pomocí příkazu DEADLOCK_PRIORITY.

SET DEADLOCK_PRIORITY

Používá následující argumenty:

  • Nízká:Je ekvivalentní prioritě uváznutí -5
  • Normální:Výchozí priorita uváznutí je 0
  • Vysoká:Je to nejvyšší priorita uváznutí 5.

Můžeme také nastavit číselné hodnoty pro prioritu uváznutí od -10 do 10 (celkem 21 hodnot).

Podívejme se na několik příkladů příkazů priority uváznutí.

Příklad 1:

Relace 1 s prioritou uváznutí:Normální (0)> Relace 2 s prioritou uváznutí:Nízká (-5)

Oběť zablokování:  Relace 2

Příklad 2:

Relace 1 s prioritou uváznutí:Normální (0)

Oběť zablokování:  Relace 1

Příklad 3

Relace 1 s prioritou uváznutí:-3> Relace 2 s prioritou uváznutí:-7

Příklad 4:

Relace 1 s prioritou uváznutí:-5

Oběť zablokování:  Relace 1

Zablokování serveru SQL pomocí grafů uváznutí

Graf uváznutí je vizuální znázornění procesů uváznutí, jejich uzamčení a oběti uváznutí. Můžeme povolit příznaky trasování 1204 a 1222 k zachycení podrobných informací o uváznutí v XML a grafickém formátu. K získání podrobností o uváznutí můžeme použít výchozí rozšířenou událost system_health. Rychlý a snadný způsob, jak interpretovat uváznutí, je pomocí grafu uváznutí. Simulujme stav uváznutí a zobrazme odpovídající graf uváznutí.

Pro tuto ukázku jsme vytvořili tabulku Zákazník a objednávky a vložili několik vzorových záznamů.

CREATE TABLE Customer (ID INT IDENTITY(1,1), CustomerName VARCHAR(20)) GO CREATE TABLE Orders (OrderID INT IDENTITY(1,1), ProductName VARCHAR(50)) GO INSERT INTO Customer(CustomerName) VALUES ('Rajendra') Go 100 S INSERT INTO Orders(ProductName) VALUES ('Laptop') Go 100

Poté jsme otevřeli nové okno dotazu a globálně povolili příznak trasování.

DBCC traceon(1222,-1)

Jakmile jsme povolili příznak trasování uváznutí, zahájili jsme dvě relace a provedli dotaz v následujícím pořadí:

  • První relace zahájí transakci za účelem aktualizace tabulky zákazníků pro číslo zákazníka 1.
  • Druhá relace zahájí transakci za účelem aktualizace tabulky objednávek pro ID objednávky 10.
  • První relace se pokusí aktualizovat tabulku objednávek pro stejné ID objednávky 10. Druhá relace již tento řádek uzamkne. Relace 1 je zablokována kvůli zámkům, které drží relace 2.
  • Nyní chceme pro relaci 2 aktualizovat tabulku zákazníků pro ID zákazníka 1. Vygeneruje to zablokování, kdy obě relace ID 63 a ID 65 nemohou pokračovat.

V tomto příkladu SQL Server vybere oběť zablokování (ID relace 65) a ukončí transakci. Pojďme načíst graf uváznutí z relace rozšířené události system_health.

SELECT XEvent.query('(event/data/value/deadlock)[1]') AS DeadlockGraph FROM ( SELECT XEvent.query('.') AS XEvent FROM ( SELECT CAST(target_data AS XML) AS TargetData FROM sys.dm_xe_session_targets st INNER JOIN sys.dm_xe_sessions s ON s.address = st.event_session_address WHERE s.NAME = ‘system_health’ AND st.target_name = ‘ring_buffer’ ) AS Data CROSS APPLY TargetData.nodes('RingBufferTarget/event[@name="xml_deadlock_report"] ') AS XEventData(XEvent) ) AS source;

Tento dotaz nám poskytuje XML uváznutí, které vyžaduje zkušeného DBA k interpretaci informací.

Toto zablokování XML uložíme pomocí přípony .XDL a když otevřeme soubor XDL v SSMS, dostaneme graf zablokování zobrazený níže.

Tento graf uváznutí poskytuje následující informace:

  • Uly procesu:  V oválu získáte informace související s procesem.
  • Uzel prostředků:  Zdrojové uzly (čtvercový rámeček) poskytují informace o objektech zapojených do transakcí spolu se zámky. V tomto příkladu zobrazuje zámky RID, protože pro obě tabulky nemáme žádné indexy.
  • Okraje:  Hrana spojuje procesní uzel a zdrojový uzel. Zobrazuje vlastníka zdroje a režim uzamčení požadavku.

Představuje oběť uváznutí přeškrtnutím oválu v grafu uváznutí.

Informace o zablokování serveru SQL Server můžete zachytit následujícími způsoby:

  • Profiler serveru SQL
  • Rozšířené události SQL Server
  • Protokoly chyb serveru SQL Server
  • Výchozí trasování na serveru SQL Server

5 typů zablokování na serveru SQL Server

1) Zablokování vyhledávání záložek

Vyhledávání záložek je běžně se vyskytující uváznutí na serveru SQL Server. Dochází k němu v důsledku konfliktu mezi příkazem select a příkazy DML (insert, update and delete). SQL Server obvykle vybere příkaz select jako oběť zablokování, protože nezpůsobuje změny dat a vrácení zpět je rychlé. Chcete-li se vyhnout vyhledávání záložek, můžete použít krycí rejstřík. V příkazech select můžete také použít nápovědu k dotazu NOLOCK, ale přečte nepotvrzená data.

2) Zablokování skenování rozsahu

Někdy používáme úroveň izolace SERIALIZABLE na úrovni serveru nebo na úrovni relace. Je to omezující úroveň izolace pro řízení souběžnosti a může vytvářet zámky skenování rozsahu namísto zámků na úrovni stránky nebo řádku. Na úrovni izolace SERIALIZABLE uživatelé nemohou číst data, pokud jsou změněna, ale čekají na potvrzení v transakci. Podobně, pokud transakce čte data, jiná transakce je nemůže upravit. Poskytuje nejnižší souběžnost, takže bychom měli používat tuto úroveň izolace ve specifických požadavcích aplikace.

3) Zablokování kaskádového omezení

SQL Server používá vztah rodič-podřízený mezi tabulkami pomocí omezení cizího klíče. V tomto scénáři, pokud aktualizujeme nebo odstraníme záznam z nadřazené tabulky, bude nutné uzamknout podřízenou tabulku, aby se zabránilo osamoceným záznamům. Chcete-li eliminovat tato zablokování, měli byste vždy nejprve upravit data v podřízené tabulce a poté nadřazená data. Můžete také pracovat přímo s nadřazenou tabulkou pomocí voleb DELETE CASCADE nebo UPDATE CASCADE. Měli byste také vytvořit vhodné indexy pro sloupce cizího klíče.

4) Zablokování paralelismu uvnitř dotazu

Jakmile uživatel odešle dotaz do dotazovacího stroje SQL, optimalizátor dotazů vytvoří optimalizovaný plán provádění. Může provádět dotaz v sériovém nebo paralelním pořadí v závislosti na ceně dotazu, maximálním stupni paralelismu (MAXDOP) a prahu ceny pro paralelismus.

V režimu paralelismu SQL Server přiřadí více vláken. Někdy se u velkého dotazu v režimu paralelismu začnou tato vlákna vzájemně blokovat. Nakonec se to změní na uváznutí. V tomto případě musíte zkontrolovat plán provádění a vaši MAXDOP a prahovou hodnotu nákladů pro konfigurace paralelismu. Můžete také zadat MAXDOP na úrovni relace a vyřešit tak situaci se zablokováním.

5) Zablokování obráceného pořadí objektů

V tomto typu uváznutí více transakcí přistupuje k objektům v jiném pořadí v T-SQL. To způsobí zablokování mezi prostředky pro každou relaci a převede ji do uváznutí. Vždy chcete přistupovat k objektům v logickém pořadí, aby to nevedlo k uváznutí.

Užitečné způsoby, jak se vyhnout a minimalizovat uváznutí serveru SQL Server

  • Snažte se, aby transakce byly krátké; tím se vyhnete dlouhodobému blokování transakce.
  • Přistupujte k objektům podobným logickým způsobem ve více transakcích.
  • Vytvořte krycí index, abyste snížili možnost uváznutí.
  • Vytvořte indexy tak, aby odpovídaly sloupcům cizího klíče. Tímto způsobem můžete eliminovat zablokování kvůli kaskádové referenční integritě.
  • Nastavte priority uváznutí pomocí proměnné relace SET DEADLOCK_PRIORITY. Pokud nastavíte prioritu uváznutí, SQL Server ukončí relaci s nejnižší prioritou uváznutí.
  • Využijte zpracování chyb pomocí bloků try-catch. Můžete zachytit chybu uváznutí a znovu spustit transakci v případě oběti zablokování.
  • Změňte úroveň izolace na READ COMMITTED SNAPSHOT ISOLATION nebo SNAPSHOT ISOLATION. Tím se změní mechanismus uzamčení serveru SQL Server. Při změně úrovně izolace byste však měli být opatrní, protože by to mohlo negativně ovlivnit ostatní dotazy.

Úvahy o uváznutí serveru SQL Server

Zablokování je přirozeným mechanismem na serveru SQL Server, který zabraňuje tomu, aby relace držela zámky a čekala na jiné zdroje. Měli byste zachytit uvázlé dotazy a optimalizovat je tak, aby nebyly ve vzájemném konfliktu. Je důležité zachytit zámek na krátkou dobu a uvolnit jej, aby jej ostatní dotazy mohli efektivně využít.

Dochází k zablokování SQL Serveru, a zatímco SQL Server interně zpracovává situace zablokování, měli byste se pokusit je minimalizovat, kdykoli je to možné. Některé z nejlepších způsobů, jak eliminovat zablokování, jsou vytvoření indexu, použití změn v kódu aplikace nebo pečlivá kontrola zdrojů v grafu zablokování. Další tipy, jak se vyhnout zablokování SQL, najdete v našem příspěvku: Předcházení zablokování SQL pomocí ladění dotazů.


  1. Rozdělení hodnot s oddělovači ve sloupci SQL do více řádků

  2. Celkový počet zámků překračuje velikost tabulky zámků

  3. Jaký je rozdíl mezi pg_table_size, pg_relation_size a pg_total_relation_size? (PostgreSQL)

  4. Použijte mysqldump k zálohování MySQL nebo MariaDB