L'idea principale del meccanismo di blocco di SQL Server è che controlla la coerenza delle transazioni. In base a questo principio, se un processo desidera eseguire operazioni di inserimento, eliminazione o aggiornamento, il motore di SQL Server blocca la riga o le righe e non consente un altro processo fino al completamento della transazione. In alcune circostanze, questo meccanismo di blocco può portare a problemi di prestazioni come pressioni di processo simultanee elevate. Quindi puoi sperimentare il deadlock (il deadlock è un problema di concorrenza in cui due transazioni vogliono accedere agli stessi dati contemporaneamente) problemi nel tuo database. In questo articolo, ci concentreremo su come evitare problemi di blocco con l'aiuto del suggerimento NOLOCK. Per prima cosa, impariamo i principali elementi essenziali e i dettagli della metodologia di lettura sporca perché il suggerimento NOLOCK può causare una lettura sporca.
Lettura sporca: In questa metodologia di lettura, il processo di lettura legge i dati non vincolati e il processo di lettura non si preoccupa delle transazioni aperte, quindi i blocchi non comportano problemi nel processo di lettura. Di conseguenza, questo tipo di lettura riduce i problemi di blocco. Tuttavia, la metodologia di lettura sporca presenta pro e contro perché la lettura sporca può causare problemi di incoerenza nel set di risultati dell'istruzione SELECT. Come già notato, questo set di risultati può includere dati di transazioni non vincolate, ecco perché dobbiamo considerare la lettura sporca quando decidiamo di fare questo tipo di lettura. Non possiamo essere sicuri dell'accuratezza delle righe che facciamo durante la lettura sporca perché queste righe possono essere ripristinate. D'altra parte, questo tipo di lettura ci consente di evitare problemi di blocco e di aumentare le prestazioni di SQL Server.
NOLOCK: Il livello di isolamento predefinito di SQL Server è Read Committed e in questo livello di isolamento SQL Server non consente di leggere gli oggetti bloccati che sono bloccati da transazioni non vincolate. Inoltre, questi oggetti bloccati possono essere modificati in base all'escalation del blocco.
Nota:in questo articolo sul concetto principale di blocco di SQL Server puoi trovare dettagli sul blocco e sull'escalation dei blocchi.
Immagina di avere due utenti del database e questi utenti vogliono eseguire l'aggiornamento e selezionare l'operazione sul database. Un primo utente inizia ad aggiornare una particolare riga nella tabella e poi l'altro utente vuole leggere la stessa riga. Questi due utenti eseguono il seguente aggiornamento e selezionano le istruzioni, come illustrato nell'immagine sottostante.
In questo caso, l'utente2 attende almeno 10 secondi, quindi la transazione verrà annullata dall'utente1, quindi utente2 può leggere la riga verde perché la riga bloccata verrà rilasciata da utente1. Questo è il comportamento predefinito del livello di isolamento Read Committed di SQL Server.
Ora dimostreremo questo caso in SQL Server. Per prima cosa creeremo la tabella FruitSales e le sue righe.
CREATE TABLE FruitSales (Id INT IDENTITY (1,1) PRIMARY KEY, [Name] Varchar(20) , SalesTotal Float) GO INSERT INTO FruitSales VALUES ('Apple',10) ,('Orange',8), ('Banana',2)
In questo passaggio, apriremo due finestre di query di SQL Server Management Studio ed eseguiremo la query utente1, quindi eseguiremo la query utente2.
---USER1---- BEGIN TRAN UPDATE FruitSales SET SalesTotal =20 WHERE Id=2 WAITFOR DELAY '00:00:10' ROLLBACK TRANSACTION ---USER2---- SET STATISTICS TIME ON SELECT * FROM FruitSales WHERE Id=2
Come puoi vedere nell'immagine sopra, la seconda query attende fino al rollback della transazione utente1.
Ora discuteremo del suggerimento NOLOCK e dei dettagli sull'utilizzo. L'hint NOLOCK è l'hint di tabella più popolare utilizzato dagli sviluppatori di database e dagli amministratori per eliminare i problemi di blocco nei database di SQL Server. Con l'aiuto del suggerimento tabella NOLOCK, possiamo leggere oggetti bloccati (riga, pagina o tabella) che sono bloccati da transazioni aperte. L'hint NOLOCK sovrascrive il comportamento predefinito di Query Optimizer di SQL Server in modo che l'istruzione select possa leggere gli oggetti bloccati.
Ora aggiungeremo l'hint NOLOCK all'istruzione select user2, quindi avvieremo l'aggiornamento user1 e quindi eseguiremo l'istruzione select user2.
---USER1---- BEGIN TRAN UPDATE FruitSales SET SalesTotal =20 WHERE Id=2 WAITFOR DELAY '00:00:10' ROLLBACK TRANSACTION ---USER2---- SET STATISTICS TIME ON SELECT * FROM FruitSales WITH(NOLOCK) WHERE Id=2
In questo passaggio, spiegheremo come influenzare l'hint NOLOCK sull'istruzione select user2. Utente1 esegue l'istruzione aggiornata in una transazione esplicita, quindi utente2 esegue l'istruzione select e il set di risultati restituisce senza indugio il completamento della transazione. Questa è l'idea principale di NOLOCK, legge oggetti bloccati.
Ora ci concentreremo sul set di risultati dell'istruzione select. L'istruzione user2 select ha recuperato il valore SalesTotal 20 ma il valore effettivo di SalesTotal è ancora 8. Tieni presente che se stai utilizzando il suggerimento tabella NOLOCK nell'istruzione select potresti dover affrontare questo tipo di risultati di dati imprecisi.
Suggerimento: La parola chiave "CON" è una funzionalità obsoleta, quindi Microsoft consiglia di non utilizzarla nello sviluppo del nuovo database e di rimuovere la parola chiave "CON" negli sviluppi attuali. Puoi trovare l'utilizzo del suggerimento NOLOCK senza la parola chiave "CON".
---USER1---- BEGIN TRAN UPDATE FruitSales SET SalesTotal =20 WHERE Id=2 WAITFOR DELAY '00:00:10' ROLLBACK TRANSACTION SELECT * FROM FruitSales WHERE Id=2 --USER2--- SELECT * FROM FruitSales (NOLOCK) WHERE Id=2
Inoltre, l'hint della tabella READUNCOMMITTED è equivalente all'hint NOLOCK e possiamo usare l'hint READUNCOMMITTED invece dell'hint NOLOCK.
SELECT * FROM FruitSales (READUNCOMMITTED) WHERE Id=2
Anche così, c'è un caso particolare sul suggerimento NOLOCK che non può superare la barriera di chiusura. Se c'è qualche processo che altera una tabella, il suggerimento NOLOCK non può superare questo tipo di blocco e non può continuare l'operazione di lettura. Il motivo di questo problema è che l'hint NOLOCK acquisisce il blocco Sch-S (stabilità dello schema) e l'istruzione ALTER TABLE acquisisce il blocco SCH-M (modifica dello schema), quindi si verifica un conflitto.
Per prima cosa, impareremo la tabella Object_Id di FruitSales con l'aiuto della seguente query.
select OBJECT_ID('FruitSales')
Eseguire la seguente query utente1 e quindi eseguire la query utente2. Di conseguenza, la query utente2 ritarderà il completamento del processo di modifica della tabella utente1.
--USER1--- BEGIN TRAN ALTER TABLE FruitSales ADD ColorofFruit varchar(200) WAITFOR DELAY '00:00:35 GO COMMIT TRAN --USER2--- SELECT * FROM FruitSales (NOLOCK) WHERE Id=2
Apri la nuova finestra della query ed esegui la query seguente. Questa query aiuterà a scoprire il tipo di blocco delle query utente1 e utente2.
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_id, Lock_owner_address FROM sys.dm_tran_locks where resource_associated_entity_id =647673355
Ora esamineremo la matrice di compatibilità del blocco per l'interazione SCH-M e SCH-S. La matrice descrive che l'interazione SCH-M e SCH-S provoca un conflitto.
Conclusione
In questo articolo, abbiamo menzionato il processo di lettura sporca e il suggerimento NOLOCK. L'utilizzo del suggerimento NOLOCK è un metodo efficace per leggere una pagina bloccata, ma presenta anche alcuni vantaggi e svantaggi. Per questo motivo, devi considerare il suggerimento NOLOCK prima di usarlo.
Riferimenti
Guida al blocco delle transazioni e al controllo delle versioni delle righe di SQL Server
Suggerimenti (Transact-SQL) – Tabella
IMPOSTA IL LIVELLO DI ISOLAMENTO DELLA TRANSAZIONE (Transact-SQL)