Could you hire me? Contact me if you like what I’ve done in this article and think I can create value for your company with my skills.

July 19, 2012 / by Zsolt Soczó

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:

Could you hire me? Contact me if you like what I’ve done in this article and think I can create value for your company with my skills.

LEAVE A COMMENT

7 COMMENTS

  • hron84 July 19, 2012

    Bakker, az utolsot nem lehetett trivialis megoldani…

  • Soczó Zsolt July 20, 2012

    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.

  • Csaba February 11, 2014

    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….

  • Soczó Zsolt February 13, 2014

    Miért nem jó erre a profiler?

  • Csaba February 14, 2014

    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 :-(