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)
 Help with query

Author  Topic 

lebedev
Posting Yak Master

126 Posts

Posted - 2007-01-15 : 19:59:11
I have the following three statements that insert, delete and query the same table. Consider a scenario where multiple clients connect and execute any of the three statements. In this scenario, it takes several seconds to execute the last statement and it becomes a real performance bottleneck. Under normal conditions the third statement runs in milliseconds, but under heavy load it takes up to 60 seconds to complete! So, I assume the problem is lock contention.

We are using default (READ COMMITTED) transaction isolation level.

Is there anything I can change in the following statements that will help optimize the third statement and reduce lock contention?

Thanks.

Alec

1) INSERT INTO DB_ACTIVE_TRANSACTION (TIMESTAMP , APP_SERVER_TAG)
OUTPUT Inserted.COMMIT_NUMBER VALUES (GETDATE(), N'myserver');

2) DELETE FROM DB_ACTIVE_TRANSACTION
WHERE COMMIT_NUMBER = 123
AND APP_SERVER_TAG = N'myserver'

3) IF EXISTS (SELECT * FROM DB_ACTIVE_TRANSACTION)
SELECT MIN(COMMIT_NUMBER)-1 FROM DB_ACTIVE_TRANSACTION
ELSE SELECT IDENT_CURRENT('DB_ACTIVE_TRANSACTION')



SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2007-01-16 : 07:18:14
Why don't you use SCOPE_IDENTITY() function instead?


Peter Larsson
Helsingborg, Sweden
Go to Top of Page

lebedev
Posting Yak Master

126 Posts

Posted - 2007-01-16 : 10:56:33
Given that DB_ACTIVE_TRANSACTION is the only table with an identity column, SCOPE_IDENTITY() will return the same value as IDENT_CURRENT(). So, I guess I could use it instead.

1. But how would that improve the situation?

2. Could anybody explain what kind of locks each of the three statements in my first post impose on the DB_ACTIVE_TRANSACTION table?

3. Which statements will block on each other under READ COMMITTED transaction isolation level? My guess is that statement 3 will contend for locks with statement 2, but not 1.

Thanks.

Alec
Go to Top of Page

SwePeso
Patron Saint of Lost Yaks

30421 Posts

Posted - 2007-01-16 : 11:01:10
Well, you have a multisuer environment.
See this taken from Books Online

IDENT_CURRENT
Returns the last identity value generated for a specified table in any session and any scope.

SCOPE_IDENTITY
Returns the last IDENTITY value inserted into an IDENTITY column in the same scope. A scope is a module -- a stored procedure, trigger, function, or batch. Thus, two statements are in the same scope if they are in the same stored procedure, function, or batch.


Peter Larsson
Helsingborg, Sweden
Go to Top of Page

lebedev
Posting Yak Master

126 Posts

Posted - 2007-01-16 : 12:17:58
Thank you, I have read the BOL description of both functions.
I have multiple clients updating server database tables. Each client needs to know the LAST identity value inserted in DB_ACTIVE_TRANSACTION by ANY other client. Therefore, I don't think that SCOPE_IDENTITY will work in my case.

I appreciate your feedback.

I just browsed through sp_who2 and SQL Server Profiler results and confirmed that there are a lot of clients trying to executed statement 3) and are blocked by some client trying to execute statement 1) or 2). Is there a way to reduce this lock contention on DB_ACTIVE_TRANSACTION table?

Thanks.

Alec
Go to Top of Page

lebedev
Posting Yak Master

126 Posts

Posted - 2007-01-16 : 13:11:39
According to sp_who2. I have process 153 running the INSERT (statement 1). Process 100 is trying to execute SELECT (statement 3) and is blocked by process 153. I also have about 20 processes, which are trying to execute SELECT (statement 3) and are blocked on process 100.

1. I don't understand why INSERT blocks SELECT in READ COMMITTED mode? Shouldn't this mode allow phantom reads?
2. What's even more interesting is why SELECTs block SELECTs?

Help, anyone?
Go to Top of Page

lebedev
Posting Yak Master

126 Posts

Posted - 2007-01-16 : 16:00:11
Ok, after speinding the whole morning trying to chase this one down it turned out that IF EXISTS (SELECT * FROM DB_ACTIVE_TRANSACTION) was conflicting with INSERT INTO DB_ACTIVE_TRANSACTION. Note that SELECT will probably do a full table scan, which is not required. Changing "SELECT *" to "SELECT 1" fixed the locking problem.

I hope this will save somebody else's morning :)
Go to Top of Page
   

- Advertisement -