views:

1535

answers:

6

We're using a SQL Server 2005 database (no row versioning) with a huge select statement, and we're seeing it block other statements from running (seen using sp_who2). I didn't realise SELECT statements could cause blocking - is there anything I can do to mitigate this?

+2  A: 

From documentation:

Shared (S) locks allow concurrent transactions to read (SELECT) a resource under pessimistic concurrency control. For more information, see Types of Concurrency Control. No other transactions can modify the data while shared (S) locks exist on the resource. Shared (S) locks on a resource are released as soon as the read operation completes, unless the transaction isolation level is set to repeatable read or higher, or a locking hint is used to retain the shared (S) locks for the duration of the transaction.

A shared lock is compatible with another shared lock or an update lock, but not with an exlusive lock.

That means that your SELECT queries will block UPDATE and INSERT queries and vice versa.

A SELECT query will place a temporary shared lock when it reads a block of values from the table, and remove it when it done reading.

For the time the lock exists, you will not be able to do anything with the data in the locked area.

Two SELECT queries will never block each other (unless they are SELECT FOR UPDATE)

You can enable SNAPSHOT isolation level on your database and use it, but note that it will not prevent UPDATE queries from being locked by SELECT queries (which seems to be your case).

It, though, will prevent SELECT queries from being locked by UPDATE.

Also note that SQL Server, unlike Oracle, uses lock manager and keeps it locks in an in-memory linked list.

That means that under heavy load, the mere fact of placing and removing a lock may be slow, since the linked list should itself be locked by the transaction thread.

Quassnoi
Don't assume implementation details about SQL Servere's lock manager. Suffice to say is *not* a linked list.
Remus Rusanu
A: 

You could set the transaction level to Read Uncommitted

John Nolan
Isn't that the same as using (NOLOCK)? I don't really want to go that direction...
Neil Barnwell
It's the same as NOLOCK, and it's fine for read-only queries.
Andomar
No, is not fine for read only queries, since NOLOCK can *only* be applied to read-only queries, so any problem it has (and has plenty) applies to 'read-only' too. An unbalanced sheet report is still 'read-only', but hardly correct.
Remus Rusanu
+7  A: 

SELECT can block updates. A properly designed data model and query will only cause minimal blocking and not be an issue. The 'usual' WITH NOLOCK hint is almost always the wrong answer. The proper answer is to tune your query so it does not scan huge tables.

If the query is untunable then you should first consider SNAPSHOT ISOLATION level, second you should consider using DATABASE SNAPSHOTS and last option should be DIRTY READS (and is better to change the isolation level rather than using the NOLOCK HINT). Note that dirty reads, as the name clearly states, will return inconsistent data (eg. your total sheet may be unbalanced).

Remus Rusanu
Quoted that on another question: http://stackoverflow.com/questions/1018651/nolock-vs-transaction-isolation-level/1018676#1018676
streetpc
A: 

To perform dirty reads you can either:

 using (new TransactionScope(TransactionScopeOption.Required, 
 new TransactionOptions { 
 IsolationLevel = System.Transactions.IsolationLevel.ReadUncommitted }))
 {
 //Your code here
 }

or

SelectCommand = "SELECT * FROM Table1 WITH (NOLOCK) INNER JOIN Table2 WITH (NOLOCK) ..."

remember that you have to write WITH (NOLOCK) after every table you want to dirty read

despart
A: 

You might also get deadlocks:

"deadlocks involving only one table" http://sqlblog.com/blogs/alexander_kuznetsov/archive/2009/01/01/reproducing-deadlocks-involving-only-one-table.aspx

and or incorrect results:

"Selects under READ COMMITTED and REPEATABLE READ may return incorrect results."

http://www2.sqlblog.com/blogs/alexander_kuznetsov/archive/2009/04/10/selects-under-read-committed-and-repeatable-read-may-return-incorrect-results.aspx

AlexKuznetsov