Soci (Soczó Zsolt) szakmai blogja

2012.07.20.

Megoldás a deadlockos cikkhez

Heuréka! :)

Előzmény.

Az előzményben látható első deadlock lenyomata xmlben így néz ki:

[source=’xml’]




SELECT @toBalance = Balance FROM Account WITH (UPDLOCK) WHERE Id = @toAccountID



Proc [Database Id = 6 Object Id = 1965614441]



UPDATE Account SET
Balance += (@amount – @commissionAmount)
WHERE Id = @toAccountID



Proc [Database Id = 6 Object Id = 1965614441]




















[/source]

Figyeljük meg, hogy mindkét processz a “KEY: 6:72057594959101952 (8194443284a0)” kulcson várakozik, ezen vesztek össze.

Viszont az xmlben nem az van, mint a képen!!!

Az xml vége felé látszik ki-mit ownol. owner-list/owner elemek:

[source=’xml’]
















[/source]

A második processz nem U lockot tart az erőforráson, hanem S-t, Shared lockot! De miért U látszik a képen? A bugos kutya életbe!
Így már kristálytiszta a dolog. Azt nem értettem, hogy tudott kiadni az SQL Server két U lockot ugyanarra az erőforrásra. Sehogy, az elmélet jó. Csak az SSMS bugos.

Tehet, mit látunk itt tképpen? Az egyik processz tart U lockot a közös erőforrásra (owner id=”processbe41288″ mode=”U”), a másik pedig egy Shared lockot (owner id=”process3c3dc8″ mode=”S”). Miért shared az egyik? Mivel valamelyik korábbi sorban (ez nem látszik az xmlből, már lefutott) lemaradt a with(updlock) a select utáni tábla mögül.
Ez az alapállás. Aztán az egyik Update lockra akar konvertálni (waiter id=”process3c3dc8″ mode=”U” requestType=”convert”, ez nem teljesen világos miért, mivel eleve az van neki. A másik Sharedről eXclusive-ra akar konvertálni. Ez már a nem megy, mivel az X nem kompatibilis az U-val, így az nem adható ki, a második processznek várnia kell, de mivel az első által kért U sem a U-val, így összeakadnak.
Míg most sem teljesen tiszta minden, az XML-ben sem látni az összes részletet, pl. miért van az U-U konverzió, de a megoldás viszonylag 100%-ra a következő: át kell nézni a beteg tárolt eljárást, és meg kell keresni benne olyan select-et, amely az Account táblát nem updlockkal érik el. Ezekre fel kell rakni az updlockot, és valószínűleg kiesik a deadlock.
Tanulság: nem elég a deadlock graph grafikus nézetét megnézni, bele kell kukkantani az xml-be is, ha valami nem logikus.
Ezt tudva már más is találkozott ezzel: http://rusanu.com/2010/05/12/the-puzzle-of-u-locks-in-deadlock-graphs/
Szóval még nem teljesen tiszta minden, de az IT már csak ilyen, félinformációk alapján is tudni kell hibát keresni.

4 Comments

  1. Múltkor futottam bele olyanba, hogy egy SELECT nolock hinttel lockolt egy másik folyamatot :-)

    Comment by Zsolt — 2012.10.03. @ 18:31

  2. Na, ezt hogy csinálta?

    Comment by Soczó Zsolt — 2012.10.11. @ 09:21

  3. Hát úgy, hogy mégse a nolock okozta a problémát, csak még lenne mit javítani a lockok trace-lésén.

    Két dolog volt a gyanús.
    1.) Két olyan tábla akadt össze, ami egymástól független.
    2.) Nolock hint lockol.

    Aztán kis törpengéssel rájöttem, hogy olyan műveletet kell keressek a trace-ekben, ahol a két tábla 1 tranzakcióban van.

    Meg is lett, demózom:

    SESSION 1 első batch:
    BEGIN TRAN

    SESSION 1 második batch:
    UPDATE egyiktábla SET valami …

    SESSION 1 harmadik batch:
    SELECT … FROM másiktábla (NOLOCK) …

    SESSION 2:
    SELECT count(*) FROM egyiktábla

    SESSION 1 még nincs egy ideig negyik batch.

    És a lock trace nem az egész tranzakciót tette bele, csak a NOLOCK-os batch-et, azaz a legutolsó batch-et a tranzakcióból, mint lockoló folyamat.

    Comment by Zsolt — 2012.10.21. @ 08:36

  4. Óh, ez a szopás ismerős. Látsz valamit, de nem is az volt a gond okozója. Köszi az infót.

    Comment by Soczó Zsolt — 2012.10.22. @ 20:52

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

Powered by WordPress