Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why use NOLOCK and NOWAIT together?

A colleague wrote a query which uses the hints "with (NOLOCK,NOWAIT)".

e.g.

select first_name, last_name, age
from people with (nolock,nowait)

Assumptions:

NOLOCK says "don't worry about any locks at any level, just read the data now"

NOWAIT says "don't wait, just error if the table is locked"

Question:
Why use both at the same time? Surely NOWAIT will never be realised, as NOLOCK means it wouldn't wait for locks anyway ... ?

like image 304
Rich Avatar asked Feb 19 '14 15:02

Rich


People also ask

What is purpose of Nowait option?

NOWAIT is table hint and it instructs the database engine to return a message as soon as a lock is encountered on a table. Let us see an example. Lock request time out period exceeded.

Why with Nolock is used?

The WITH (NOLOCK) table hint is used to override the default transaction isolation level of the table or the tables within the view in a specific query, by allowing the user to retrieve the data without being affected by the locks, on the requested data, due to another process that is changing it.

What is the difference between Nolock and with Nolock?

The WITH (NOLOCK) option behaves like the READ UNCOMMITTED isolation level. But whereas the isolation level applies for the entire connection, WITH NOLOCK applies to a specific table. The WITH (NOLOCK) option behaves like the READ UNCOMMITTED isolation level, because the first one can't read dirty reads.

Does with Nolock prevent deadlocks?

The benefits of querying data using the NOLOCK table hint is that it requires less memory and prevents deadlocks from occurring with any other queries that may be reading similar data.


3 Answers

It's redundant (or at least, ineffective). In one query window, execute:

create table T (ID int not null)
begin transaction
alter table T add ID2 int not null

leave this window open, open another query window and execute:

select * from T WITH (NOLOCK,NOWAIT)

Despite the NOWAIT hint, and despite it being documented as returning a message as soon as any lock is encountered, this second query will hang, waiting for the Schema lock.

Read the documentation on Table Hints:

NOWAIT:

Instructs the Database Engine to return a message as soon as a lock is encountered on the table

Note that this is talking about a lock, any lock.

NOLOCK (well, actually READUNCOMMITTED):

READUNCOMMITTED and NOLOCK hints apply only to data locks. All queries, including those with READUNCOMMITTED and NOLOCK hints, acquire Sch-S (schema stability) locks during compilation and execution. Because of this, queries are blocked when a concurrent transaction holds a Sch-M (schema modification) lock on the table.

So, NOLOCK does need to wait for some locks.

like image 98
Damien_The_Unbeliever Avatar answered Dec 09 '22 23:12

Damien_The_Unbeliever


NOLOCK is the same as READUNCOMMITTED, for which MSDN states:

... exclusive locks set by other transactions do not block the current transaction from reading the locked data.

Based on that sentence, I would say you are correct and that issuing NOLOCK effectively means any data locks are irrelevant, so NOWAIT is redundant as the query can't be blocked.

However, the article goes on to say:

READUNCOMMITTED and NOLOCK hints apply only to data locks

You can also get schema modification locks, and NOLOCK cannot ignore these. If you issued a query with NOLOCK whilst a schema object was being updated, it is possible your query would be blocked by a lock of type Sch-M.

It would be interesting to see if in that unlikely case the NOWAIT is actually respected. However for your purposes, I would guess it's probably redundant.

like image 37
Sir Crispalot Avatar answered Dec 09 '22 21:12

Sir Crispalot


It does not make any sense to use them together. NOLOCK overrides the behavior of NOWAIT. Here's a demonstration of the NOWAIT Functionality. Comment in the NOLOCK and watch the records return despite the Exclusive Lock.

Create the table. Execute the 1st SSMS window without commiting the transaction. Execute the second window get an error because of no wait. Comment out the first query and execute the second query with the NOLOCK and NOWAIT. Get results. Rollback your transaction when you are done.

DDL

USE [tempbackup]
GO

/****** Object:  Table [TEST_TABLE]    Script Date: 02/19/2014 09:14:00 ******/
SET ANSI_NULLS ON
GO

SET QUOTED_IDENTIFIER ON
GO

SET ANSI_PADDING ON
GO

CREATE TABLE [TEST_TABLE](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Name] [varchar](50) NULL,
 CONSTRAINT [PK_TEST_TABLE] PRIMARY KEY CLUSTERED 
(
    [ID] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  = ON, ALLOW_PAGE_LOCKS  = ON) ON [PRIMARY]
) ON [PRIMARY]

GO

SET ANSI_PADDING OFF
GO

INSERT INTO tempbackup.dbo.TEST_TABLE(Name) VALUES ('MATT')

GO

SSMS WINDOW 1

BEGIN TRANSACTION

UPDATE tempbackup.dbo.TEST_TABLE WITH(XLOCK) SET Name = 'RICHARD' WHERE ID = 1

--ROLLBACK TRANSACTION

SSMS WINDOW 2

SELECT * FROM tempbackup.dbo.TEST_TABLE WITH(NOWAIT)
--SELECT * FROM tempbackup.dbo.TEST_TABLE WITH(NOLOCK,NOWAIT)
like image 36
Mathew A. Avatar answered Dec 09 '22 21:12

Mathew A.