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.

È stato utile?

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.

Performance Dahsboard Link

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

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top