Huvudidén med SQL Server-låsmekanismen är att den kontrollerar transaktionernas konsekvens. Enligt denna princip, om en process vill utföra infogning, radering eller uppdatering, låser SQL Server-motorn raden eller raderna och tillåter inte en annan process förrän transaktionen är slutförd. Under vissa omständigheter kan denna låsmekanism leda till prestandaproblem såsom höga samtidiga processtryck. Så du kan uppleva dödläget (deadlock är ett samtidighetsproblem där två transaktioner vill komma åt samma data samtidigt) problem i din databas. I den här artikeln kommer vi att fokusera på hur man undviker låsproblem med hjälp av NOLOCK-tipset. Låt oss först lära oss det viktigaste och detaljerna i smutsig läsningsmetodik eftersom NOLOCK-tipset kan orsaka smutsig läsning.
Smutsig läsning: I denna läsmetodik läser läsprocessen oengagerad data och läsprocessen bryr sig inte om öppna transaktioner så låsen leder inte till några problem i läsprocessen. Som ett resultat minskar denna typ av avläsning låsproblemen. Den smutsiga läsningsmetoden har dock för- och nackdelar eftersom smutsig läsning kan orsaka inkonsekvensproblem i resultatuppsättningen av SELECT-satsen. Som redan nämnts kan dessa resultatuppsättningar inkludera oengagerade transaktionsdata, det är därför vi måste ta hänsyn till den smutsiga avläsningen när vi bestämmer oss för att göra denna typ av avläsning. Vi kan inte vara säkra på noggrannheten hos rader som vi gör under smutsig läsning eftersom dessa rader kan rullas tillbaka. Å andra sidan tillåter denna typ av läsning oss att undvika låsningsproblem och att öka prestanda hos SQL Server.
NOLOCK: Standardisoleringsnivån för SQL Server är Read Committed och på denna isoleringsnivå tillåter inte SQL Server att läsa låsta objekt som är låsta av icke-committed transaktioner. Dessutom kan dessa låsta objekt ändras enligt låseskalering.
Obs:I den här huvudkonceptet för SQL Server-låsningsartikel kan du hitta detaljer om låsning och låseskalering.
Föreställ dig att du har två databasanvändare och dessa användare vill utföra uppdatering och välja operation mot databasen. En första användare börjar uppdatera en viss rad i tabellen och sedan vill den andra användaren läsa samma rad. Dessa två användare utför följande uppdatering och väljer satser, vilket illustreras i bilden nedan.
I det här fallet väntar användare2 minst 10 sekunder och sedan återställs transaktionen av användare1, och sedan användare2 kan läsa den gröna raden eftersom den låsta raden kommer att släppas av användare1. Detta är standardbeteendet för isoleringsnivån för SQL Server Read Committed.
Nu kommer vi att demonstrera detta fall i SQL Server. Först och främst kommer vi att skapa tabellen FruitSales och dess rader.
CREATE TABLE FruitSales(Id INT IDENTITY (1,1) PRIMÄRNYCKEL, [Namn] Varchar(20) ,SalesTotal Float)GOINSERT INTO FruitSales VALUES('Apple',10) ,('Orange',8), ( 'Banan',2)
I det här steget kommer vi att öppna två frågefönster i SQL Server Management Studio och exekvera användar1-frågan och sedan köra user2-fråga.
---USER1----BÖRJA ÖVERFÖRING UPPDATERA FruitSales SET SalesTotal =20 WHERE Id=2 WAITFOR DELAY '00:00:10'ÅTERKALLA TRANSAKTION ---USER2----STÄLL IN STATISTIK TID PÅ VÄLJ * FRÅN FruitSales VAR Id=2
Som du kan se i bilden ovan väntar den andra frågan tills återställningen av user1-transaktionen.
Nu kommer vi att diskutera NOLOCK-tipset och användningsdetaljer. NOLOCK-tipset är det mest populära tabelltipset som används av databasutvecklare och administratörer för att eliminera låsproblem i SQL Server-databaser. Med hjälp av NOLOCK-tabelltipset kan vi läsa låsta objekt (rad, sida eller tabell) som är låsta av öppna transaktioner. NOLOCK-tipset åsidosätter standardbeteendet för SQL Server-frågeoptimeraren så att select-satsen kan läsa de låsta objekten.
Nu kommer vi att lägga till NOLOCK-tipset till user2 select-satsen och sedan starta user1-uppdateringen och sedan köra user2 select-satsen.
---USER1----BÖRJA ÖVERFÖRING UPPDATERA FruitSales SET SalesTotal =20 WHERE Id=2 WAITFOR DELAY '00:00:10'ROLLBACK TRANSACTION ---USER2----STÄLL IN STATISTIK TID PÅ VÄLJ * FRÅN FruitSales MED (NOLOCK) WHERE Id=2
I det här steget kommer vi att förklara hur man påverkar NOLOCK-tipset på user2 select-satsen. Användare1 exekverar det uppdaterade uttalandet i en explicit transaktion och sedan kör användare2 select-satsen och resultatuppsättningen returnerar utan dröjsmål slutförandet av transaktionen. Detta är huvudidén med NOLOCK, den läser låsta objekt.
Nu kommer vi att fokusera på resultatuppsättningen av select-satsen. User2 select-satsen hämtade SalesTotal-värdet 20 men det faktiska värdet av SalesTotal är fortfarande 8. Tänk på att om du använder NOLOCK-tabelltipset i ditt select-uttryck kan du möta denna typ av felaktiga dataresultat.
Tips: Nyckelordet "WITH" är en föråldrad funktion, så Microsoft rekommenderar att du inte använder det i din nya databasutveckling och tar bort nyckelordet "WITH" i din nuvarande utveckling. Du kan hitta användningen av NOLOCK-tipset utan nyckelordet "WITH".
---USER1----BÖRJA ÖVERFÖRING UPPDATERA FruitSales SET SalesTotal =20 WHERE Id=2 WAITFOR DELAY '00:00:10'ROLLBACK TRANSACTIONSELECT * FROM FruitSales WHERE Id=2 --USER2---SELECT * FROM FruitSales (NOLOCK) WHERE Id=2
Dessutom är READUNCOMMITTED-tipset likvärdigt med NOLOCK-tipset och vi kan använda READUNCOMMITTED-tipset istället för NOLOCK-tipset.
VÄLJ * FRÅN FruitSales (READUNCOMMITTED) WHERE Id=2
Trots det finns det ett särskilt fall om NOLOCK-tipset som inte kan passera låsbarriären. Om det finns någon process som ändrar en tabell, kan NOLOCK-tipset inte övervinna denna typ av lås och kan inte fortsätta läsningen. Anledningen till detta problem är att NOLOCK-tipset förvärvar Sch-S-låset (schemastabilitet) och ALTER TABLE-satsen förvärvar SCH-M-låset (schemamodifiering), så en konflikt uppstår.
Till en början kommer vi att lära oss tabellen Object_Id of FruitSales med hjälp av följande fråga.
välj OBJECT_ID('FruitSales')
Kör följande användare1-fråga och kör sedan användar2-frågan. Som ett resultat kommer användar2-frågan att fördröja slutförandet av ändringsprocessen för user1.
--USER1---BEGIN TRANALTER TABELL FruitSalesADD ColorofFruit varchar(200) WAITFOR DELAY '00:00:35GOCOMMIT TRAN --USER2---SELECT * FROM FruitSales (NOLOCK) WHERE Id=2
Öppna det nya frågefönstret och kör följande fråga. Den här frågan hjälper dig att ta reda på låstypen för användar1- och användare2-frågor.
SELECT Resource_type, Resource_database_id, Resource_description, Resource_associated_entity_id, Resource_lock_partition, Request_mode, Request_type, Request_status, Request_session_id, Request_request_id, Request_owner_type, Request_owner_type, Request_where_owner_add.
Nu ska vi kolla in låskompatibilitetsmatrisen för SCH-M och SCH-S interaktion. Matrisen beskriver att SCH-M och SCH-S interaktion orsakar en konflikt.
Slutsats
I den här artikeln nämnde vi den smutsiga läsprocessen och NOLOCK-tipset. Att använda NOLOCK-tipset är en effektiv metod för att läsa en låst sida men det har också vissa fördelar och nackdelar. Av denna anledning måste du överväga NOLOCK-tipset innan du använder det.
Referenser
SQL Server Transaction Locking och Row Versioning Guide
Tips (Transact-SQL) – Tabell
STÄLL IN TRANSAKTIONSISOLERINGSNIVÅ (Transact-SQL)