Problema di deadlock di SQL Server 2005
-
22-07-2019 - |
Domanda
Sto riscontrando un problema di deadlock quando provo a bloccare alcuni record in modo che nessun processo (servizio Windows) selezioni gli elementi per ripararli, quindi aggiorni lo stato e quindi restituisca un recordset.
Potete per favore fatemi sapere perché ricevo il problema di deadlock quando viene invocato questo proc?
CREATE PROCEDURE [dbo].[sp_LoadEventsTemp]
(
@RequestKey varchar(20),
@RequestType varchar(20),
@Status varchar(20),
@ScheduledDate smalldatetime = null
)
AS
BEGIN
declare @LoadEvents table
(
id int
)
BEGIN TRANSACTION
if (@scheduledDate is null)
Begin
insert into @LoadEvents (id)
(
Select eventqueueid FROM eventqueue
WITH (HOLDLOCK, ROWLOCK)
WHERE requestkey = @RequestKey
and requesttype = @RequestType
and [status] = @Status
)
END
else
BEGIN
insert into @LoadEvents (id)
(
Select eventqueueid FROM eventqueue
WITH (HOLDLOCK, ROWLOCK)
WHERE requestkey = @RequestKey
and requesttype = @RequestType
and [status] = @Status
and (convert(smalldatetime,scheduleddate) <= @ScheduledDate)
)
END
update eventqueue set [status] = 'InProgress'
where eventqueueid in (select id from @LoadEvents)
IF @@Error 0
BEGIN
ROLLBACK TRANSACTION
END
ELSE
BEGIN
COMMIT TRANSACTION
select * from eventqueue
where eventqueueid in (select id from @LoadEvents)
END
END
Grazie in anticipo.
Soluzione
I deadlock si verificano più spesso (nella mia esperienza) quando risorse diverse sono bloccate all'interno di transazioni diverse in ordini diversi.
Immagina 2 processi usando le risorse A e B, ma bloccandoli in ordini diversi.
- Il processo 1 blocca la risorsa A, quindi la risorsa B
- Il processo 2 blocca la risorsa B, quindi la risorsa A
Quindi diventa possibile:
- Il processo 1 blocca la risorsa A
- Il processo 2 blocca la risorsa B
- Il processo 1 tenta di bloccare la risorsa B, quindi si interrompe e attende il processo 2
- Il processo 2 tenta di bloccare la risorsa A, quindi si interrompe e attende il processo 1
- Entrambi i processi si stanno aspettando, Deadlock
Nel tuo caso avremmo bisogno di vedere esattamente dove cade l'SP a causa di un deadlock (l'aggiornamento immagino?) e qualsiasi altro processo che faccia riferimento a quella tabella. Potrebbe essere un trigger o qualcosa del genere, che viene quindi bloccato in una tabella diversa, non nella tabella che stai aggiornando.
Quello che vorrei fare è usare Sintassi OUTPUT di SQL Server 2005 per evitare di dover utilizzare la transazione ...
UPDATE
eventqueue
SET
status = 'InProgress'
WHERE
requestkey = @RequestKey
AND requesttype = @RequestType
AND status = @Status
AND (convert(smalldatetime,scheduleddate) <= @ScheduledDate OR @ScheduledDate IS NULL)
OUTPUT
inserted.*
Altri suggerimenti
Hai un indice non cluster definito come:
CREATE NONCLUSTERED INDEX NC_eventqueue_requestkey_requesttype_status
ON eventqueue(requestkey, requesttype, status)
INCLUDE eventqueueid
e un altro su eventqueueid?
A proposito la conversione della colonna scheduleddate
nel tipo smalldatetime
impedirà qualsiasi uso di un indice su quella colonna.
Prima di tutto, mentre esegui SQL Server, ti consiglio di installare Performance Dashboard, uno strumento molto utile per identificare quali blocchi sono attualmente in esecuzione sul server.
In secondo luogo, traccia una traccia del tuo SQL Server utilizzando SQL Profiler (già installato) e assicurati di selezionare nella selezione Eventi la voce Blocca > Grafico del deadlock che mostrerà cosa sta causando il deadlock.
Devi avere ben chiaro in che cosa consiste un deadlock per iniziare a risolverlo. Quando viene effettuato l'accesso a qualsiasi tabella o riga sul DB viene effettuato un blocco.
Consente di chiamare SPID 51 e SPID 52 (SPID = ID processo SQL)
SPID 51 blocca la cella A
SPID 52 blocca la cella B
se sulla stessa transazione lo SPID 51 richiede la cella B, attenderà lo SPID 52 fino al rilascio.
se nella stessa transazione SPID 52 richiede la cella A, si ottiene un deadlock perché questa situazione non finirà mai (51 in attesa di 52 e 52 per 51)
Devo dirti che non è facile risolvere i problemi, ma devi scavare più a fondo per trovare la risoluzione