Je reçois des blocages intermittents avec la procédure stockée suivante. Il est exécuté une fois par minute. Il est en production depuis 1+ ans et nous n'obtenons généralement pas cette erreur mais il arrive parfois … il lance des exceptions 3 à 5 fois par jour dans l'un de nos environnements … c'est le même environnement que d'autres instances ne jetez pas l'erreur. La procédure stockée a été faite afin qu'elle ne puisse fonctionner qu'une fois à la fois, mais peut-être que la façon dont nous le faisons n'est pas correcte?
Voici l'erreur:
System.Web.HttpUnhandledException: Exception du type 'System.Web.HttpUnhandledException' a été levée. —> System.Data.SqlClient.SqlException: La transaction (ID de process 60) a été bloquée sur les ressources de locking avec un autre process et a été choisie comme victime de blocage. Réexécutez la transaction.
Voici la procédure stockée:
SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[requestUpdate] AS SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; BEGIN TRAN DECLARE @StartDate datetime, @EndDate datetime, @Throttle bit, @Expired bit SELECT @Throttle = 0 SELECT @Expired = 0 SELECT TOP 1 @StartDate = uq.StartDate, @EndDate = uq.EndDate FROM UpdateQueue uq WITH(TABLOCK,XLOCK) ORDER BY ID DESC -- PREVENT ANOTHER REQUEST IF THIS SP HAS BEEN -- CALLED IN THE LAST FORTY SECONDS. IF DATEADD(SECOND,-40,GETDATE()) < @StartDate BEGIN SELECT @Throttle = 1 END -- CREATE ANOTHER REQUEST IF THE CURRENT ONE -- HAS NOT COMPLETED IN THE LAST FIVE MINUTES. IF @StartDate <= DATEADD(MINUTE,-5,GETDATE()) BEGIN SELECT @Expired = 1 END -- HAS THE CURRENT REQUEST EXPIRED? IF @EndDate IS NULL AND @Expired = 1 BEGIN INSERT INTO UpdateQueue (RequestID, StartDate) OUTPUT 'EXPIRED' AS Result, INSERTED.RequestID AS RequestID VALUES (NEWID(), GETDATE()) END -- HAS THE CURRENT REQUEST COMPLETED AND YOU ARE NOT THROTTLING -- OR HAVE THERE NOT BEEN ANY REQUESTS YET? ELSE IF (@EndDate IS NOT NULL AND @Throttle = 0) OR @StartDate IS NULL BEGIN INSERT INTO UpdateQueue (RequestID, StartDate) OUTPUT 'STARTED' AS Result, INSERTED.RequestID AS RequestID VALUES (NEWID(), GETDATE()) END -- Running ELSE BEGIN SELECT 'RUNNING' AS Result, NULL AS RequestID END COMMIT
Je soupçonne qu'il s'agit d'un verrou particulier détenu pendant plus longtime que votre connection est prête à attendre. Sans quelque chose pour tuer une transaction de longue durée, ici, vous allez vous heurter à cela car lorsque la connection expire, SQL Server force l'attente à se terminer et détruit le verrou entrant en tant que victime de blocage.
Longue histoire courte: un certain process (pas celui détaillé ici) verrouille la table, provoquant une impasse.
Examiner ce qui se passe d'autre lorsque vous rencontrez l'impasse – existe-t-il une sauvegarde en cours, ou quelque chose d'autre qui verrouille cette table?