Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
371 views
in Technique[技术] by (71.8m points)

sql server - What effect does HOLDLOCK have on UPDLOCK?

I have seen many examples of the HOLDLOCK hint being used in combination with UPDLOCK (like this). However Microsoft's documentation for these hints make it seem like HOLDLOCK should be redundant, since UPDLOCK already persists the lock until the end of the transaction. (Also it seems to say that HOLDLOCK only applies to shared locks anyway.)

How does HOLDLOCK affect the query, if at all?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

It has a large impact.

The Update lock takes an Update lock on the row, Intent update on the page and a shared lock on the table / database.

This does not stop other queries from accessing the data within the table, since the locks on the page / database are purely share locks. They just may not clash locks against the individual row / page / table by attempting to perform an operation that would contradict locks. If that occured the request would queue behind the current locks and wait for it to come available before it could proceed.

By using holdlock, the query is being forced to be serialised, locking the table exclusively until the action has completed. This prevents anyone from reading the table unless the nolock hint is used, allowing a potentially dirty read.

To see the effect, generate an example table 'foo' and put some trash data in it.

begin tran

select * from foo with (updlock)
where tableid = 1
-- notice there is no commit tran

Open another window and try:

select * from foo

The rows come back, now commit the original query transaction. Re-run it altered to use holdlock as well:

begin tran

select * from foo with (updlock, holdlock)
where tableid = 1

Go back to the other window and try select the data again, the query will not return values since it is blocked by the exclusive lock. Commit the transaction on the first window and the results to the second query will appear since it is no longer blocked.

Final test is to use the nolock, run the transaction again using updlock and holdlock. then run the following in the second window:

select * from foo (nolock)

The results will come back automatically, since you have accepted the risk of a dirty read (read uncommitted).

So it is seen to have a large impact, in that you are forcing actions against that table to be serialised which might be what you want (depending on the update being made) or will create a very large bottleneck on that table. If everyone did that to a busy table with long running transactions then it would cause significant delays within an application.

As with all SQL features, when used correctly they can be powerful, but mis-use of a feature / hint can cause significant problems. I prefer to use hints as a last resort for when I have to override the engine - not as a default approach.

Edit as Requested : Tested in SQL 2005, 2008, 2008R2 (All Enterprise) - all installed on pretty much default settings, test database created using all defaults (just entered the name of the DB only).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...