I’ve lately come across a rather frustrating situation where SQL server refuses to issue locks only against a primary key when a statement like this select * from table with (rowlock updlock) where key=value
is executed against it. Now don’t get me wrong here, it does lock the row but it goes one step farther and locks the table too.
I’ve read up about SQL lock escalation and I’ve looked at using specific indexes in the lock hints but you see, this just isn’t practical when there are numerous indexes in a table with millions of records and concurrent updates that need to happen on those records. For a small table and a specific query it’s possible to get the desired behaviour, but when the table has a large width (many columns) and there are numerous processes using the data, this method melts down and can become a real point of contention.
What I’d like to see added is a new lockhint suck as PKLock (which would stand for Primary Key Lock) which would issue a lock against the primary key of a row and anytime an index, a table scan or other method is used to get the row, it would check this lock and honour it instead of locking the entire table.
As such a table lock would not need to be issued and this would greatly increase the capacity for parallel execution of code against the DB.
Please weigh in on this idea and point out any flaws which it might have, ways that it could be improved or other elements that should be added to resolve my dilemma.
EDIT
@Remus
If I execute this query
begin transaction
select lockname from locks where lockname='A'
update Locks Set locked=1 where lockname='A'
and then this query:
begin transaction
select lockname from locks where lockname='A'
Row A is returned in both examples before committing the transactions. This is reading behind the update, not blocking.
A successful solution should do the following without specifying indexes to use:
- With Query 1: Read and lock A, update A
- With Query 2: Read and lock B, update B, Commit query 2
- With Query 2: Read B and be blocked until Locks on A are released
- With Query 1: Commit Query 1
- With Query 2 :Read and lock A, update A, Commit query 2