Please start any new threads on our new site at https://forums.sqlteam.com. We've got lots of great SQL Server experts to answer whatever question you can come up with.

 All Forums
 SQL Server 2005 Forums
 Transact-SQL (2005)
 The dreaded LOCKS

Author  Topic 

CorkMan
Starting Member

6 Posts

Posted - 2010-11-08 : 04:58:09
We have an automated process than INSERT data to our production database on request. This may happen up to 100 times per day. Our database has about 15 clients and each one is reading and saving data to the database so there are many transactions per second. What seems to be happening during the INSERT of production data is that some of the tables LOCK during the INSERT and the 15 clients pause and cannot read from the tables. Is there any way to stop this happening? In all of our SELECT queries and Stored Procedures we specify (NOLOCK), but is there anything similar for the INSERT that can keep the tables available to all clients?

Thanks,

Lumbago
Norsk Yak Master

3271 Posts

Posted - 2010-11-08 : 06:47:20
Wow...using nolock across the board sounds like a horrible idea! Fortunately there is no way of preventing a lock when inserting data. The best way to remove locking problems is to have proper indexing in place. Always make sure you have a clustered index on every table and make every insert/update as fast as possible by doing proper performance tuning. If you insert large chunks of data at a time try to sort the data in the order of the clustered index before you insert in to the production table. This can increase insert performance dramatically.

- Lumbago

My blog (yes, I have a blog now! just not that much content yet)
-> www.thefirstsql.com
Go to Top of Page

Lumbago
Norsk Yak Master

3271 Posts

Posted - 2010-11-08 : 06:51:43
You should also consider enabling the isolation level READ_COMMITTED_SNAPSHOT ->
http://msdn.microsoft.com/en-us/library/tcbchxcb(VS.80).aspx

- Lumbago

My blog (yes, I have a blog now! just not that much content yet)
-> www.thefirstsql.com
Go to Top of Page

GilaMonster
Master Smack Fu Yak Hacker

4507 Posts

Posted - 2010-11-08 : 07:38:34
quote:
Originally posted by CorkMan
In all of our SELECT queries and Stored Procedures we specify (NOLOCK)


Wow. Ever single query and proc could return inconsistent and possibly completely wrong information and you're happy with that?
See - [url]http://sqlblog.com/blogs/andrew_kelly/archive/2009/04/10/how-dirty-are-your-reads.aspx[/url]

Massive locking is, in the vast majority of cases, the result of two things - poorly written queries and inadequate indexing. I strongly suggest that you get a performance tuning specialist in for a few days to have a look over your system.

Consider snapshot isolation, just make sure your TempDB is configured for the additional load it'll have.

--
Gail Shaw
SQL Server MVP
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-11-08 : 07:55:27
"In all of our SELECT queries and Stored Procedures we specify (NOLOCK)"

I think this is a really bad idea. I answered a similar question just recently, if you want to read my explanation of why I think its bad here's the link:

http://www.sqlteam.com/forums/topic.asp?TOPIC_ID=152332#598659
Go to Top of Page

CorkMan
Starting Member

6 Posts

Posted - 2010-11-09 : 07:05:37
Ok thanks guys, unfortunately I inherited this code from some others but am trying my best to get it to as standard a state as possible.

To clarify what I need to do it Set READ_COMMITTED_SNAPSHOT on for the database and remove the (NOLOCK)on the SELECTs. How then will I resolve the issues with two Writes happening at the same time to the same table. I believe this is why the NOLOCKs were initially implemented. Is the use of ROWLOCK better for this type of lock error or does SQL automatically queue the INSERTS or UPDATES to the same table?

Thanks for advice so far, very good eye opening stuff.

================================================
Knowing is not enough you must apply! Willing is not enough you must do!
Go to Top of Page

GilaMonster
Master Smack Fu Yak Hacker

4507 Posts

Posted - 2010-11-09 : 07:14:26
Nolock will have no effect on the two concurrent writes scenario. It only affects reads.

One of the writes will wait for the other to complete.

--
Gail Shaw
SQL Server MVP
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-11-09 : 10:07:14
"What seems to be happening during the INSERT of production data is that some of the tables LOCK during the INSERT and the 15 clients pause and cannot read from the tables."

READ_COMMITTED_SNAPSHOT should fix this (and so should NOLOCK [although as explained best not to use that). Are you seeing this blocking where NOLOCK is in place currently? (Maybe NOLOCK is not RELIABLY in place on all tables / views / everywhere that the tables are referenced - in which case READ_COMMITTED_SNAPSHOT will do a better job as it will impact all SELECT statements without further changes.)

If you are doing SELECT and UPDATE in one "unit of work" then there is the possibility of blocking between processes. In particular if Process-1 updates Table-A and then tries to update Table-B and "at the same time" Process-2 updates Table-B and then tries to update Table-A. One of the processes should be treated as the deadlock-victim and be aborted (and rolled back) in such circumstances.

In such circumstances NOLOCK will probably make things worse because it may have successfully read the data that Process-2 had written to Table-B (which has now been rolled back) and may therefore be trying to perform some action dependant on that data (apart from a user acting upon their viewing of that data too).

If that is not the scenario that is giving you trouble we probably need you to describe the actual scenario in detail so that folk can better understand it and advise - a list of the steps that the processes performance such as "SELECT TableA WHERE ID=1234, UPDATE TableA SET Col1 = 'XXX' WHERE ID=1234 ..."
Go to Top of Page

namman
Constraint Violating Yak Guru

285 Posts

Posted - 2010-11-09 : 15:21:36
quote:

Nolock will have no effect on the two concurrent writes scenario. It only affects reads.


Hi GalaMonster,

Just curious, how a nolock read can affect other reads since it does NOT genarate any lock?

CorkMan
NOLOCK may cause serious problems as Kristen described but it is not the cause of deadlock. Pay attention to Kristen message:
quote:

If you are doing SELECT and UPDATE in one "unit of work" then there is the possibility of blocking between processes. In particular if Process-1 updates Table-A and then tries to update Table-B and "at the same time" Process-2 updates Table-B and then tries to update Table-A. One of the processes should be treated as the deadlock-victim and be aborted (and rolled back) in such circumstances.

In such circumstances NOLOCK will probably make things worse because it may have successfully read the data that Process-2 had written to Table-B (which has now been rolled back) and may therefore be trying to perform some action dependant on that data (apart from a user acting upon their viewing of that data too).



Also, please provide sql statements (captured on Profiler) that involve the deadlocks so that people have more info to help.
Go to Top of Page

Lamprey
Master Smack Fu Yak Hacker

4614 Posts

Posted - 2010-11-09 : 15:41:08
An insert by definition creates a lock..

In the past you could add a NOLOCK to an insert, but that didn't really make any sense and SQL did not honor it anyway. I think with 2008 on it will error if you try to put a nolock on the table you are inserting into.
Go to Top of Page

GilaMonster
Master Smack Fu Yak Hacker

4507 Posts

Posted - 2010-11-09 : 15:41:32
You misunderstand me.

The nolock hint only affects read queries. Queries that change data (update, delete) will ignore the nolock hint if it's applied. It is only for read queries.

--
Gail Shaw
SQL Server MVP
Go to Top of Page

Kristen
Test

22859 Posts

Posted - 2010-11-10 : 02:32:58
"NOLOCK may cause serious problems as Kristen described but it is not the cause of deadlock"

You sure? I have no evidence of this but:

IF EXISTS (SELECT * FROM MYTABLE WITH (NOLOCK)) WHERE MyID = 1234)
BEGIN
UPDATE MyTable
SET Col1 = 'Foo'
WHERE MyID = 1234
END

Another session may have a lock on MyID=1234 and, depending on isolation and Transaction state in both processes, that could presumably block the SELECT if it did not have the NOLOCK hint.

So this statement could be blocked BEFORE the UPDATE rather than WHEN the Update was reached.

Just assume considerably more complex logic, but where the SELECT's have NOLOCK hints and thus don't block.

I think this could lead to Deadlock on the Updates whereas, without the NOLOCKs, the process might block earlier such that Deadlock did not occur.

Pure conjecture though!
Go to Top of Page

namman
Constraint Violating Yak Guru

285 Posts

Posted - 2010-11-10 : 11:45:15
quote:

You misunderstand me.

The nolock hint only affects read queries. Queries that change data (update, delete) will ignore the nolock hint if it's applied. It is only for read queries.


I got it!

quote:

"NOLOCK may cause serious problems as Kristen described but it is not the cause of deadlock"

You sure? I have no evidence of this but:


IF EXISTS (SELECT * FROM MYTABLE WITH (NOLOCK)) WHERE MyID = 1234)
BEGIN
UPDATE MyTable
SET Col1 = 'Foo'
WHERE MyID = 1234
END


Another session may have a lock on MyID=1234 and, depending on isolation and Transaction state in both processes, that could presumably block the SELECT if it did not have the NOLOCK hint.

So this statement could be blocked BEFORE the UPDATE rather than WHEN the Update was reached.

Just assume considerably more complex logic, but where the SELECT's have NOLOCK hints and thus don't block.

I think this could lead to Deadlock on the Updates whereas, without the NOLOCKs, the process might block earlier such that Deadlock did not occur.

Pure conjecture though!



Hi Kristen,

Yes, I am (at least for now ). In your sql, if you take WITH(NOLOCK) out (with repeatable isolation level), deadlock will occur in concurring enviroment. I should explain more about my idea .... but a bit busy. I come back latter.

Happy to discuss about lock .... hopefully other people also have idea on this.

Go to Top of Page

Michael Valentine Jones
Yak DBA Kernel (pronounced Colonel)

7020 Posts

Posted - 2010-11-10 : 12:47:53
Why are you using repeatable read isolation level? That would likely cause the problems you describe.

Why not use the normal read committed isolation level?



CODO ERGO SUM
Go to Top of Page

GilaMonster
Master Smack Fu Yak Hacker

4507 Posts

Posted - 2010-11-10 : 15:39:39
quote:
Originally posted by namman

In your sql, if you take WITH(NOLOCK) out (with repeatable isolation level), deadlock will occur in concurring enviroment.


Optimise your queries. Vast majority of deadlocks are the result of one or more of:
Too high isolation level (do you have a reason for repeatable read?)
Poorly written queries
Non-optimal indexes.

--
Gail Shaw
SQL Server MVP
Go to Top of Page

namman
Constraint Violating Yak Guru

285 Posts

Posted - 2010-11-10 : 16:44:42
quote:

IF EXISTS (SELECT * FROM MYTABLE WITH (NOLOCK)) WHERE MyID = 1234)
BEGIN
UPDATE MyTable
SET Col1 = 'Foo'
WHERE MyID = 1234
END


In your sql, if you take WITH(NOLOCK) out (with repeatable isolation level), deadlock will occur in concurring enviroment. I should explain more about my idea .... but a bit busy. I come back latter.



I use Kristen example to describe that WITH(NOLOCK) is not the cause of deadlocks. I do NOT mean we should use WITH(NOLOCK) or repeatable read in that example. Using lock mode and isolation levels should base on business requirement. There is no "One-Size-Fits-All". All have advantages and disadvantages.....

quote:

Why not use the normal read committed isolation level?


That level (or read_committed_snapshot) may have problems in that example too....
Go to Top of Page
   

- Advertisement -