Empêcher l'exécution d'une procédure stockée deux fois en même temps
-
05-07-2019 - |
Question
J'ai une procédure stockée pour SQL Server 2000 qui ne peut exécuter qu'une seule instance à un moment donné. Existe-t-il un moyen de vérifier et d’assurer que la procédure n’est pas en cours d’exécution?
Idéalement, j'aimerais que le code soit autonome et efficace (rapide). Je ne souhaite pas non plus créer une table temporaire globale pour vérifier son existence, car si la procédure échoue pour une raison quelconque, elle sera toujours considérée comme en cours d'exécution ...
J'ai cherché, je ne pense pas que cela ait été demandé pour le moment. Si tel est le cas, désolé.
La solution
oui il y a un moyen. utilisez ce qui est appelé Verrous d'application SQL Server .
EDIT: oui, cela fonctionne également dans SQL Server 2000 .
Autres conseils
Vous pouvez utiliser sp_getapplock sp_releaseapplock comme dans l'exemple trouvé dans Verrouiller un Procédure stockée à usage unique uniquement .
Mais, est-ce ce que vous essayez vraiment de faire? Essayez-vous d'obtenir une transaction avec un niveau d'isolement élevé ? Vous auriez probablement aussi intérêt à gérer ce type de concurrence au niveau de l'application, car les langages de niveau supérieur ont généralement de meilleures primitives pour ce type de choses.
que diriez-vous de verrouiller une table factice? Cela ne provoquerait aucune impasse en cas d'échec.
Au début de la procédure, vérifiez si une donnée est verrouillée sinon verrouillée
En fin de procédure, déverrouillez la donnée.
c'est-à-dire
SELECT @IsLocked=IsLocked FROM CheckLockedTable Where spName = 'this_storedProcedure'
IF @IsLocked = 1
RETURN
ELSE
UPDATE CheckLockedTable SET IsLocked = 1 Where spName = 'this_storedProcedure'
.
.
.
-- At end of Stored Procedure
UPDATE CheckLockedTable SET IsLocked = 0 Where spName = 'this_storedProcedure'
L'un des liens externes initiaux partagés dans les réponses contenait des informations utiles, mais personnellement, je préfère que les réponses / extraits autonomes soient ici, ici, sur la page de question relative au dépassement de capacité. Voir l'extrait ci-dessous pour ce que j'ai utilisé et résolu mon problème (similaire). Si vous avez des problèmes (ou des suggestions d’ajustement), envoyez-nous un message
IF EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[MyLockedAndDelayedStoredProcedure]') AND type in (N'P', N'PC'))
DROP PROCEDURE [GetSessionParticipantAnswersFromEmailAddressAndSessionName]
GO
CREATE PROCEDURE [MyLockedAndDelayedStoredProcedure]
@param1 nvarchar(max) = ''
AS
BEGIN
DECLARE @LockedTransactionReturnCode INT
PRINT 'MyLockedAndDelayedStoredProcedure CALLED at ' + CONVERT(VARCHAR(12),GETDATE(),114);
BEGIN TRANSACTION
EXEC @LockedTransactionReturnCode =sp_getapplock @Resource='MyLockedAndDelayedStoredProcedure_LOCK', @LockMode='Exclusive', @LockOwner='Transaction', @LockTimeout = 10000
PRINT 'MyLockedAndDelayedStoredProcedure STARTED at ' + CONVERT(VARCHAR(12),GETDATE(),114);
-- Do your Stored Procedure Stuff here
Select @param1;
-- If you don't want/need a delay remove this line
WAITFOR DELAY '00:00:3'; -- 3 second delay
PRINT 'MyLockedAndDelayedStoredProcedure ENDED at ' + CONVERT(VARCHAR(12),GETDATE(),114);
COMMIT
END
-- https://gist.github.com/cemerson/366358cafc60bc1676f8345fe3626a3f