SQL Clone
SQLServerCentral is supported by Redgate
Log in  ::  Register  ::  Not logged in

My SELECT statement has hung!

 One of the first roadblocks many developers run into when using SQL Server for the first time is firing off a query that simply selects data, and having the query never return a result. After spending several minutes of their precious life-force watching nothing happen, they get aggravated, cancel the query, and try again, and again, and again. The query just sits there and does nothing but mock the query writer. This is especially frustrating when the table only contains a couple hundred rows and you know that one of the undeniable constants of the universe is that SQL Server should return that result set immediately, but here it is 4:02 later, 4:03 later, 4:04 later and still no results. Report writers also often run into this problem.  Pretty soon, you will hear the evil phrase "Access would have done it by now."  Yikes.

The cold hard truth is that you probably haven’t done anything wrong. It’s a shocking realization, but here we go: By default, SQL Server will place locks on data even when you are simply SELECTing data!

OK, now that you have fallen out of your chair, whimpered, and returned to your former place, let’s dive into this. There is actually a logical reason. Basically, SQL Server does stuff super fast, and it has to make sure that multiple users aren’t trying to read and update the same data at the same time. This ensures that what you see is really what is on the disk. These locks that are put on the data when you select are known as read locks. These locks keep other processes from coming along and changing the data that is in your result set before your process finishes selecting the data. Imagine if you got back a result set with half the records having been updated by another process, and the other half not updated by that process. If you work with financial data, particularly highly volatile data (think stocks) this would be very, very, very bad. SQL Server takes the conservative road and ensures this won’t happen.

If your trying to select data that already has a lock on it, say from another process UPDATEing records you query will pick up, then your query will wait for those locks to clear before it can place a lock of it's own on the data.  Of course, if the other query is well-behaved, then the lock will disappear soon and your back on track.  However, like drivers, queries do not always behave and a hung or long running query will stop your SELECT indefinately.

So, what to do?  If your not running a highly volatile system and don’t need to worry about some records being updating during your during your select, then there is a simple answer. Actually, you have a choice:
1) Check out Books Online for “SET TRANSACTION ISOLATION LEVEL” and considering setting this value to the “READ UNCOMMITTED” setting. After issueing that command, your queries will no longer worry about running into locks they find on other records, and they will come back to you, or
2) In your FROM clause, add the “WITH (NOLOCK)" hint after you table name. This will also tell the server to ignore it if a record has a lock on it, but to simply take whatever value happens to be there. For example: SELECT * FROM CUSTOMER_DATA WITH (NOLOCK)

For a little further reading, try searching for “SQL Server” and “Dirty Reads.” A dirty read is the short-hand name for ignoring locks and simply reading the data from disk, whatever it may be.


Posted by czeshirecat on 13 January 2014

Thanks very much for this. I'm inexperienced with sql server and I didn't have this problem with MySql.

So I'm hoping that this explains why, if I call a function (that opens its own connection, performs a simple select, then closes the connection) from within a transaction then the select query freezes.

Leave a Comment

Please register or log in to leave a comment.