Question

My boss keeps on forcing me to write SELECT queries with with (nolock) to prevent deadlocks. But AFAIK, Select statements by default does not have locks, so selecting with with (nolock) and selecting without doesn't make any difference. Please correct me if I am wrong.

The two queries:

SELECT * from EMP with (nolock)

SELECT * from EMP 

Isn't both are same. If I don't put nolock will it be prone to deadlocks? Please tell me what should I use.

Was it helpful?

Solution

Nolocks should be used with extreme caution. The most common understanding of nolock (read uncommitted) hint is that it reads data that has not been committed yet. However, there are other side effects that can be very dangerous. (search for "nolock" and "page splits")

There's a really good write up here... https://www.itprotoday.com/sql-server/beware-nolock-hint

In short, "nolocking"ing everything is not always a good idea... if ever.

OTHER TIPS

Assuming we have default Transaction Isolation Level READ COMMITTED ,there is a chance for a dead lock even in a very simple SELECT statement , Imagine a scenario where User1 is only reading data and User2 trys to Update some data and there a non-clustered index on that table, it is possible.

  1. User1 is reading Some Data and obtains a shared lock on the non-clustered index in order to perform a lookup, and then tries to obtain a shared lock on the page contianing the data in order to return the data itself.

  2. User2 who is writing/Updating first obtains an exlusive lock on the database page containing the data, and then attempts to obtain an exclusive lock on the index in order to update the index.

SELECT statements do indeed apply locks unless there is a statement at the top of the query SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED.

By all means use WITH (NOLOCK) in SELECT statement on tables that have a clustered index, but it would be wiser to only do so if there's a need to.

Hint: The easiest way to add a clustered index to a table is to add an Id Primary Key column.

The result set can contain rows that have not yet been committed, that are often later rolled back.

If WITH(NOLOCK) is applied to a table that has a non-clustered index then row-indexes can be changed by other transactions as the row data is being streamed into the result-table. This means that the result-set can be missing rows or display the same row multiple times.

READ COMMITTED adds an additional issue where data is corrupted within a single column where multiple users change the same cell simultaneously.

Bearing in mind the issues WITH(NOLOCK) causes will help you tune your database.

As for your boss, just think of them as a challenge.

One benefit of using a select statement with no deadlock is that it excludes data that is currently locked. This can result in a faster query and help prevent your application from crashing in the event of a lock in the database.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top