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.
| Author |
Topic |
|
AskSQLTeam
Ask SQLTeam Question
0 Posts |
Posted - 2005-04-01 : 08:04:08
|
| David writes "We're currently developing a multithreading windows service which is simply dispatching work to the server farm. The deadlock occured in one of the stored procedures. The sp is pretty simple, it first gets the minimum id in the table, then set machine name and windows service name for that row. Finally return that row.here is the sp:-----------------------------------------------------CREATE PROCEDURE dbo.GetNextUnprocessedMessage@StateNew varchar(20),@StateNext varchar(20),@WinServiceName varchar(20),@MachineName varchar(20)ASDECLARE @id intBEGIN TRANSACTIONSET @id = -1;-- grab the next available message, if presentSET @id = ( SELECT MIN(unprocessed_message_id) FROM unprocessed_message WITH (HOLDLOCK, ROWLOCK) WHERE state = @StateNew)-- update the state of the row we just selected (and locked) so that it can't-- be grabbed by anyone else using this procedureUPDATE unprocessed_messageWITH(ROWLOCK)SET state = @StateNext, win_service_name = @WinServiceName, machine_name = @MachineNameWHERE unprocessed_message_id = @idIF (@@ERROR > 0)BEGIN ROLLBACK TRANSACTION RAISERROR('Error fetching next message', 15, -1, @@ERROR)END-- return the newly updated rowSELECT *FROM unprocessed_messageWHERE unprocessed_message_id = @idCOMMIT TRANSACTIONGO--------------------------------------------------we set clustered index (unprocessed_message_id) on unprocessed_message, and the isolation level is default (read committed).please help me on this issue. Thank you.David " |
|
|
TG
Master Smack Fu Yak Hacker
6065 Posts |
Posted - 2005-04-01 : 10:48:29
|
I believe the problem is that 2 different processes have grabbed the same unprocessed_message_id and are waiting for the other to release the lock it so they can continue with the update, resulting in deadlock.What you should do is construct you sp logic SOMETHING like this:--with default isolation level (read committed)--Reserve the next available (unreserved) recordUPDATE unprocessed_message SET state = @Reserved ,win_service_name = @WinServiceName ,machine_name = @MachineNameWHERE unprocessed_message_id = (SElect min(unprocessed_message_id) From unprocessed_message Where state = @unprocessed)--Now you have a reserved record without holding a lock--and without colliding with another process--Return reserved record for processingSelect <colList>From unprocessed_messageWhere state = @reservedAND win_service_name = @WinServiceNameAND machine_name = @MachineName Be One with the OptimizerTG |
 |
|
|
|
|
|
|
|