Soci (Soczó Zsolt) szakmai blogja

2012.07.19.

Furcsa deadlockok

Mostanában valahogy utolérnek a code review jellegű munkák, amiket egyébként nagyon szeretek, mivel ezek általában intenzív, agyalós nyomozások szoktak lenni, amit imádok.
Az előzőben deadlockok jelentek meg egy SQL Server alapú rendszerben, nagyobb terhelés esetén. A deadlockokat általában elég egyszerű megfogni, az SQL Server Profiler Deadlock graph tálcán kínálja az összeakadt folyamatokat és erőforrásokat. A legtöbb deadlock vagy conversion deadlock, amelyek repeatable read izolációs szinten végrehajtott select-update vált ki, vagy a más sorrendben elért táblák miatt előálló deadlock.
Esetünkben a selectek ki voltak egészítve with(updlock)-kal, amely pont a konverziós deadlockot hivatott megakadályozni (nem kell a shared lockot átkonvertáltni update lockká, mivel már a select is update lockot használ).
No, de ami most más volt mint szokott, hogy általam eddig nem látott volt a deadlock graph. Megörökítettük az utókornak, íme (shift clickkel kell megnyitni, így külön ablakban nyílik meg, így össze lehet nézni a szöveggel):

Mi a furcsa benne? Középen van a két erőforrás, amely esetünkben ugyanaz a tábla. Ez még ok, de a HoBtId is ugyanaz, azaz ugyanarról a sorról van szó.

Update: ez marhaság. a HobtID csak azt mondja meg, hogy azonos allokációs egység, heap vagy index (btree). De az, hogy ugyanarra a sorra várakoznak igaz, a waitresource=”KEY: 6:72057594959101952 (8194443284a0)” attributumból látszik, de ez nem látszik a grafikus nézeten.

Még ez is rendben van. Nézzük meg, milyen lockok vannak kiosztva! A bal és a jobb oldali processz is update lockot tart az erőforrásokon, amelyek a korábbiak alapján úgy néz ki egy erőforrást reprezentálnak. Na, itt van a bibi. Két update lock nem kompatibilis, pont erre találták ki őket, hogy ne szeressék egymást. Akkor hogy tud kiosztani a szerver mégis ilyeneket? Igazából ez a talány, utána már természetes, nem tudnak fogni még egy update és egy exclusive lockot a közös sorokra. Mi a túró történik itt?

Nekem van egy bűnbakom, aki ezt a furcsaságot csinálja, de csak pár nap múlva írom le, amikor már többet tudok róla, hogy a módosítások után megjavult-e a rendszer.

Aki látott már ilyet, kérem ossza meg velünk.

Zárásul csemegének itt van egy nagyobb gráfocska, amikor többen is összeakadnak:

7 Comments

  1. Bakker, az utolsot nem lehetett trivialis megoldani…

    Comment by hron84 — 2012.07.19. @ 21:16

  2. Nem a darabszám a lényeg, hanem, hogy megtalálod-e a kiváltó mintát.
    De egyébként még nincs pont az ügy végén, habár egyelőre a deadlockok megszűntek, de jelentős átalakítások leszek, után lehet csak nyugodtan hátradőlni.
    Meg a retry logika is elkerülhetetlen pár helyen, mivel 100%-ig sose lehet kizárni a deadlockokat.

    Comment by Soczó Zsolt — 2012.07.20. @ 08:53

  3. […] Előzmény. […]

    Pingback by Soci blog » Blog Archive » Megoldás a deadlockos cikkhez — 2012.07.20. @ 09:54

  4. […] Előzmény. […]

    Pingback by Megoldás a deadlockos cikkhez - Soczó Zsolt Szakmai blogja - devPortal — 2012.07.23. @ 14:04

  5. Sziasztok,

    valamelyikőtöknek nincs a tarsolyában egy olyan script, amelyik az épen aktuális, esetleg performancia gondot is okozó deadlock-okat kilistázná?

    Az sp_lock nem egy bőbeszédű eljárás, ez a script pedig szerintem nem a valós aktiv deadlock-okat mutatja:

    declare @xml xml

    select @xml = target_data
    from sys.dm_xe_session_targets
    join sys.dm_xe_sessions on event_session_address = address
    where name = ‘system_health’

    if (substring(cast (serverproperty(‘ProductVersion’) as nvarchar(20)), 1, 5) = ‘10.00’ and cast(substring(cast (serverproperty(‘ProductVersion’) as nvarchar(20)), 7, 4) as int) < 2757)
    or
    (substring(cast (serverproperty(‘ProductVersion’) as nvarchar(20)), 1, 5) = ‘10.50’ and cast(substring(cast (serverproperty(‘ProductVersion’) as nvarchar(20)), 7, 4) as int) < 1702)
    begin
    select cast (
    replace (
    replace (
    replace (
    replace (
    replace (
    replace(replace(replace(xev.xv.value (‘(data/value)[1]’, ‘nvarchar(max)’), ‘ ‘,’!L$%&’),’%&!L$’,”),’!L$%&’,’ ‘),
    ‘<victim-list’, ‘<victim-list’),
    ”, ”),
    ”, ”),
    char(10), ”),
    ‘”> <victimProcess’)
    as xml)
    from
    (select @xml as tg) AS Data
    cross apply tg.nodes (‘RingBufferTarget/event[@name=”xml_deadlock_report”]’) as xev (xv)
    end
    else
    begin
    select cast(xev.xv.value (‘(data/value)[1]’, ‘nvarchar(max)’) as xml)
    from
    (select @xml as tg) AS Data
    cross apply tg.nodes (‘RingBufferTarget/event[@name=”xml_deadlock_report”]’) as xev (xv)
    end

    legalábbis nem hinném, hogy esetemben jelenleg közel 1000 deadlock lenne a DB-ben Az kicsit “too much” lenne….

    Comment by Csaba — 2014.02.11. @ 14:06

  6. Miért nem jó erre a profiler?

    Comment by Soczó Zsolt — 2014.02.13. @ 09:51

  7. Szia Zsolt,

    köszi az infót. Az igazság az, hogy nagyon elvesztem a profilerben, annyira ritkán kell használjam ( szerencsére ), hogy lövésem sincs, mi(ke)t kapcsoljak be, hogy azt lássam, amire kiváncsi vagyok :-(

    Comment by Csaba — 2014.02.14. @ 09:06

RSS feed for comments on this post.

Sorry, the comment form is closed at this time.

Powered by WordPress