Take the 2-minute tour ×
Database Administrators Stack Exchange is a question and answer site for database professionals who wish to improve their database skills and learn from others in the community. It's 100% free, no registration required.

I was reading the answer from here (from stackoverflow, I think should ask in here)

NOLOCK means placing no locks at all.

Your query may returns portions of data as of before UPDATE and portions as of after UPDATE in a single query.

I get that nolock will not place lock to the table, so other people can query the same time.

From the answer and example it show, it fetch data while the data is being updating.

Why does that happen?

I am assuming for normal select it will try place lock on table, so when update statement is executed, it place a lock on the row or page. Then when I try to run select statement, it cannot put the lock until the update statement lock is released.

But in this case because the select statement doesn't try to put lock on the table, so it can run without waiting for the update statement release the lock?

share|improve this question
    
So that is actually that is nothing to do with NoLock? –  King Chan Jan 25 '12 at 16:27

2 Answers 2

up vote 9 down vote accepted

It is not quite true that NOLOCK means placing no locks at all. Queries under this hint will still take Sch-S locks and (possibly HOBT locks).

Under read committed isolation level SQL Server will (usually) take row level S locks and release them as soon as the data is read. These are incompatible with the X locks held on uncommited updates and thus prevent dirty reads.

In the example in the linked answer the SELECT query is not blocked when it encounters a modified row so reading partial updates is quite likely.

It can also happen at default read committed isolation level too though that a SELECT reads some rows with the "before" value and others with the "after" value. It is just needed to engineer a situation where

  1. Select query reads value of row R1 and releases its S lock
  2. Update query updates R2 and takes an X lock
  3. Select query tries to read R2 and is blocked.
  4. Update query updates R1 and takes an X lock.
  5. Update transaction commits thus releasing its locks and allowing the Select to read R2

This type of situation might arise for example if the SELECT and UPDATE are using different indexes to locate the rows of interest.

Example

CREATE TABLE T
(
X INT IDENTITY PRIMARY KEY,
Y AS -X UNIQUE,
Name varchar(10),
Filler char(4000) DEFAULT 'X'
)


INSERT INTO T (Name)
SELECT TOP 2500 'A'
FROM master..spt_values

Now in one query window run

DECLARE @Sum int

SELECT 'SET @@ROWCOUNT' WHERE 1=0

WHILE (@@ROWCOUNT = 0)
SELECT @Sum = SUM(LEN(Name))
FROM T 
WHERE Y IN (-1, -2500)
HAVING SUM(LEN(Name)) = 3

This will run in an infinite loop. In another run

UPDATE T 
SET Name=CASE WHEN Name = 'A' THEN 'AA' ELSE 'A' END

This will likely stop the loop in the other query (try again if not) meaning that it must have read either A,AA or AA,A

share|improve this answer
3  
+1 this type of behaviour can also occur at REPEATABLE READ. e.g. sqlblog.com/blogs/alexander_kuznetsov/archive/2010/10/21/… –  Paul White Jan 25 '12 at 19:11

The hint NOLOCK is equivalent to the transaction isolation level READ UNCOMMITTED, just restricted to the scope of one table access method.

What RU does that makes the non-committed appear on your resultset? Hmm, actually is a question of "what it not does. I'll explain below.

Well (this is a gross simplification, I know) MSSQL (in its' default behavior) is a lock engine - which means that it uses lock to read/write data on a consistent manner. In this oversimplified explanation, MSSQL uses two kinds of locks: shared lock and exclusive lock.

An shared(S) lock is a lock that allow an resource (which can be a row, page of rows or even an entire table) to be read - but not allows an write to it. So if transaction T1 puts a S lock on R1 row, all transactions that tries to read R1 will get that read, but while the S lock is alive nobody can write to R1.

An exclusive(X) lock is the counterpart of the shared lock. It allows exclusive access to a resource - no other transaction can read or write except the one that got the X lock. In the above example, if T1 got not an S lock but an X lock on R1, no one except T1 can read or write it.

That's the teory. The isolation levels honor the locks, and respect their prevalence and characteristics. All, except READ UNCOMMITTED. It simple gives a * (put your bad mouth word of your preference here) to the locks regarding the reading - you still cannot update the row another transaction got an X lock. It simply says: "I'll read everything that's relevant to the query plan - disregard what locks are on it." And do it.

share|improve this answer
1  
"just restricted to the scope of one query" should be "restricted to the scope of one table access method" - NOLOCK is a table hint, not a query hint. –  Paul White Jan 25 '12 at 19:05
    
@SQLKiwi: Thank you, corrected. –  Fabricio Araujo Jan 25 '12 at 19:08

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.