SELECTy nemohou uváznout s jinými SELECT, protože získávají pouze sdílené zámky. Říkáte, že bychom měli zvážit, že tyto SELECTy nyní „vyžadují výhradní zámky pro čtení“, ale to pro nás není možné uvažovat, protože 1) neexistuje nic takového jako exlusive read lock
a 2) čtení nezískává exkluzivní zámky.
Ale kladete si obecnější otázku, zda mohou jednoduché příkazy uváznout na mrtvém bodě. Odpověď je definitivní, hlasité ANO . Zámky jsou získávány při provádění, nejsou analyzovány předem a tříděny a poté získány v určitém pořadí. Pro engine by nebylo možné předem znát potřebné zámky, protože závisí na skutečných datech na disku a číst data, která engine potřebuje k ... uzamknutí dat.
Zablokování mezi jednoduchými příkazy (SELECt vs. UPDATE nebo SELECT vs. DELETE) v důsledku odlišného pořadí přístupu k indexu je docela běžné a je velmi snadné je prozkoumat, diagnostikovat a opravit. Všimněte si však, že existuje vždy jde o operaci zápisu, protože čtení se nemůže vzájemně blokovat. V této diskusi by přidání nápovědy UPDLOCK nebo XLOCK do SELECT mělo být považováno za zápis. Nepotřebujete ani JOIN, sekundární index může způsobit problém s pořadím přístupu vedoucí k uváznutí, viz Zablokování čtení/zápisu .
A nakonec napsání SELECT FROM A JOIN B
nebo napsáním SELECT FROM B JOIN A
je zcela irelevantní. Optimalizátor dotazů může změnit pořadí přístupu, jak uzná za vhodné, skutečný text dotazu nijak neurčuje pořadí provádění.
Aktualizováno
Obávám se, že recept na vykrajovátka neexistuje. Řešení bude záviset případ od případu. Nakonec, v databázových aplikacích jsou uváznutí faktem života. Chápu, že to může znít absurdně, jako například „přistáli jsme na Měsíci, ale nemůžeme napsat správnou databázovou aplikaci“, ale ve hře jsou silné faktory, které do značné míry zaručují, že aplikace nakonec uvíznou. Šťastná uváznutí jsou ten nejjednodušší řešení chyb, jednoduše znovu přečíst stav, použít logiku, přepsat nový stav. Nyní, když již bylo řečeno, existuje několik osvědčených postupů, které mohou dramaticky snížit frekvenci zablokování až do té míry, že jsou všechny téměř vymizené:
- Snažte se mít konzistentní vzor přístupu pro zápisy . Mít jasně definovaná pravidla uvádějící věci jako „transakce se vždy uvádí v tomto pořadí:
Customers
->OrderHeaders
->OrderLines
.' Upozorňujeme, že příkaz musí být splněn v rámci transakce . V zásadě seřaďte vše tabulky ve vašem schématu a určete, že všechny aktualizace musí probíhat v pořadí podle pořadí. To se nakonec scvrkává na disciplinu kódu jednotlivého přispěvatele, který kód píše, protože musí zajistit, že zapisuje aktualizaci ve správném pořadí v rámci transakce. - Zkraťte dobu trvání z píše. Obvyklá moudrost zní takto:na začátku transakce proveďte všechna čtení (přečtěte si stávající stav), poté zpracujte logiku a vypočítejte nové hodnoty a na konci transakce zapište všechny aktualizace. Vyhněte se vzoru jako 'čtení->zápis->logika->čtení->zápis', místo toho udělejte 'čtení->čtení->logika->zápis->zápis'. Skutečné řemeslo samozřejmě spočívá v tom, jak se vypořádat se skutečnými, skutečnými, individuálními případy, kdy se zdánlivě musí musíte udělat zápisy uprostřed transakce. Zde je třeba uvést zvláštní poznámku o specifickém typu transakcí:transakcích řízených frontou, které podle definice zahajují svou činnost vyřazením (=zápisem) z fronty. Tyto aplikace bylo vždy notoricky obtížné psát a byly náchylné k chybám (zejména uváznutí), naštěstí existují způsoby, jak to udělat, viz Použití tabulek jako front .
- Snižte počet čtení. Skenování tabulek je the nejčastější příčinou uváznutí. Správné indexování nejen odstraní zablokování, ale může také zvýšit výkon v procesu.
- Izolace snímku . Toto je nejbližší věc, kterou dostanete k bezplatnému obědu, pokud jde o zamezení uváznutí. Záměrně jsem to dal jako poslední, protože to může maskovat jiné problémy (jako nesprávná indexace) místo jejich opravy.
Pokuste se tento problém vyřešit pomocí LockCustomerByXXX
Obávám se, že přístup nefunguje. Pesimistické zamykání se neškáluje. Optimistický souběh
aktualizace jsou způsob, jak jít, pokud chcete mít nějaký slušný výkon.