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.
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
2 COMMENTS
Szia!
Érdemes megnézni ezt http://www.wisdomforce.com/dweb/resources/docs/MSSQL2005_ORACLE10g_compare.pdf az irományt, többek között az SQL2K5 és az ORA közötti lockolási különbségeket is taglalja, mint pl.
“Oracle provides similar performance with block based row versioning on the same hardware and OS compared to MSSQL with no row versioning”
PLusz SQL2K5-ben default ki van kapcsolva a row versioning, míg ORA-ban ki sem lehet kapcsolni. Ez azért sztem jelent valamit :-)
Üdv, L.
Lies, Damn Lies and Benchmarks. :)
Annak idején azt hittem, hogy a @ táblák a memóriában tárolódnak, a #-osok meg a TempDB-ben. Ezért kihoztam, hogy a @-osak gyorsabbak. Nem akartam hazudni, de valahogy mégis csak az jött ki, a legnagyobb jószándékom és őszinte igyekezetem ellenére.
Szóval minden ilyen szám, ez gyorsabb, az gyorsabb ingoványos vizekre evez.
Ennek ellenére biztos vagyok benne, hogy az Ora izolációs kódja sokkal öregebb, ezért sokkal optimalizáltabb, mint az SQL 2005 tempdbs megoldása.
Ennek ellenére örülünk neki. :)