Sokan azt hiszik, ha beraknak néhány tsql utasítást egy tranzakciós blokkba, akkor máris védettek más kapcsolatok hatásaitól. Természetesen ez messzemenőkig nem igaz, a default read commmitted szint mellett simán szúrhatnak be vagy törölhetnek sorokat, miközben egy select dolgozik rajta, mivel a select mindig csak azon a kis tartományon tart locokot, amit éppen olvasgat. Azon a pár lapon pl.
Ez egész gondolatmenet innen indult. A szerző azt bizonygatja, tök jó a NOLOCK hint, mert így gyorsabb lesz a query. Persze, valamelyest biztos, hisz ilyenkor egyáltalán nem rak lockokat a szerver az olvasott sorokra. A hozzászólásokban persze jól odamondják a jóembernek, hogy ne beszélj ilyenekről, mert sok hozzá nem értő ember azt hiszi, ez valami tuning lehetőség, miközben súlyos adathibák léphetnek fel a read UNcommitted szinten, a NOLOCK miatt.
Ez egyik hozzászólásban volt egy érdekes gondolat:
“Anyway, there is a little catch with NOLOCK however. SQL Server mostly uses unordered clustered index scans when NOLOCK is specified, this can cause duplicate records to be returned when page splits occur while your query is scanning the index.”
Szóval nem feltétlen csak olyan sorok jöhetnek be, amiket esetleg egy másik tranzakció még visszavon, hanem még ugyanaz a sor is bejöhet duplikálva. Persze, aki ésszel használja, pl. statisztikai funkciókra, azt ez nem értekli, de fontos, hogy mindenki realizálja a NOLOCK veszélyeit.
A hozzászólásokban van egy link erre a cikkre, innen bedig erre. Mindkettő az izolációs szintek anomáliát boncolgatja, érdemes átfutni őket.
Mi a helyzet a 2005-ben, a snapshot read committed bekapcsolása után? Nos, ebben az esetben a read committed szintű izolációs szint esetén a select a párhuzamos módosítás előtti eredményeket adja vissza, ami egy bár időben eltolt, de konzisztens állapotot állít elő. Ezt a szintet nyilván azért szeretjük, mert az írók nem blokkolják az olvasókat és vica versa. Ugyanezért szokták bevetni 2000-ben a NOLOCKot, csak itt nincs meg viszont az inkonzisztens adatok veszélye. Ezért szeretjük ezt az újítást, és erre irigykedett minden sql server programozó az orákulumra 2005 előtt.
De persze ennek is meg van az ára. Minden egyes, a select futása alatti módosítást bevezet a szerver a tempdb-be, így mikor odaér a select a módosított adathoz, akkor átnyúlnak a tempdbbe, és onnak veszik el a sor módosítás előtti állapotát. Ez azért eléggé erőforrásigényes lehet. Különösen érdekes lehet a helyzet, ha egy order by-os selectet kérünk le. Ha az order by pont a clustering key mentén működik, akkor normál esetben egyszerűen olvasni kell a szervernek az adatlapokat, sorban, ez piszok gyors. Mi van viszont ebben a helyzetben? Foglalmam sincs, ilyenkor hogyan hajtja végre a kérést. Ha valaki tudja, ne tartsa magában. Köszönöm.