Deadlock

Fermé
Kagami - 9 juil. 2013 à 13:24
blux Messages postés 26529 Date d'inscription dimanche 26 août 2001 Statut Modérateur Dernière intervention 13 décembre 2024 - 18 juil. 2013 à 13:49
bonjour ,
j ai eu un message d'erreur :
La transaction (ID de processus 52) a été bloquée sur les ressources verrou par un autre processus et a été choisie comme victime. Réexécutez la transaction.
je pensais connaitre la procédure stockée où se produit ce problème, mais je ne sais pas comment le détecter , il y a 2 tables qui veulent faire la même action ou quelque chose du genre de deadlock .. je ne sais pas exactement de quoi s'agit de phénomène....
Voici la procédure :


USE [Pharmatica]
GO
/****** Object:  StoredProcedure [dbo].[FinDel]    Script Date: 07/09/2013 09:24:36 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[FinDel]
@iIdVente int,
@NewNumVenteErrorChek int=0
AS
declare @iIdArticle int,
@dPrix decimal(16,2),
@iStock int,
@iQteReserve int,
@iQteServie int,
@sDate varchar(50),
@iUnite int,
@iUniteGratuiteVente int,
@iIdTransVente int,
@iMois int,
@iAnnee int,
@iNbreVente int,
@iQteVendu int,
@iSomme int,
@iConsommation int,
@iVenteMois int,
@fPrixVente decimal(16,2),
@iMAJQteStock int,
@iStockTotal int,
@iMAJUniteGratuite int,
@iUniteGratuitePdt int,
@QteReserve int, @StockTotal int
begin transaction
	SET @sDate = convert(varchar(50),getdate(),103)
	declare encours cursor FOR 
		SELECT id_trans_vente,transactions_lingne_ventes.id_article,prix_unit_ttc_article,stock_article_stock,qte_reserve_article_stock,qte_servie_ligne,unite_gratuite_article_stock
		FROM transactions_lingne_ventes,article_stock
		WHERE id_vente=@iIdVente
		AND transactions_lingne_ventes.id_article=article_stock.id_article
		AND transactions_lingne_ventes.prix_unit_ttc_article=article_stock.prix_vente_article_stock
	OPEN Encours
		FETCH NEXT FROM Encours
		INTO @iIdTransVente,@iIdArticle,@dPrix,@iStock,@iQteReserve,@iQteServie,@iUnite
		WHILE @@FETCH_STATUS = 0
		BEGIN
		IF(@iQteServie>0)
		begin		
			IF(@iUnite>=@iQteServie)
			begin
				SET @iUniteGratuiteVente = @iQteServie
			end
			else
			begin
				SET @iUniteGratuiteVente = @iUnite
			end
			SET @iUnite = @iUnite - @iUniteGratuiteVente
			UPDATE transactions_lingne_ventes SET unite_gratuite_ligne=@iUniteGratuiteVente WHERE id_trans_vente=@iIdTransVente
			SET @NewNumVenteErrorChek = @@ERROR
			UPDATE article_stock SET unite_gratuite_article_stock = @iUnite WHERE id_article=@iIdArticle AND prix_vente_article_stock LIKE @dPrix
			SET @NewNumVenteErrorChek = @@ERROR
		end
		else
		begin
			IF(@iUnite>0)
			begin
				SET @iUniteGratuiteVente = @iQteServie
			end
			else
			begin
				SET @iUniteGratuiteVente = 0
			end
			--set @iUnite = @iUnite - @iUniteGratuiteVente
			UPDATE transactions_lingne_ventes SET unite_gratuite_ligne=@iUniteGratuiteVente WHERE id_trans_vente=@iIdTransVente
			SET @NewNumVenteErrorChek = @@ERROR
		end
 
 
 
 
 
------------------------------------------------------------------------------------------------------------------------------------------
		--------------------MAJ historique article et nbre vente article
		--exec MAJArticle @iIdArticle,@iQteServie,1,@sDate
 
	SET @iNbreVente = (SELECT DISTINCT NBR_SORTIE_ARTICLE FROM ARTICLE WHERE ID_ARTICLE=@iIdArticle)
	IF @iNbreVente= NULL
		begin
			SET @iNbreVente = 0
		end
	SET @iNbreVente = @iNbreVente	+ 1
 
	SET @iQteVendu = (SELECT DISTINCT NBR_VENTE_ARTICLE FROM ARTICLE WHERE ID_ARTICLE=@iIdArticle)
	IF @iQteVendu=NULL
		begin
			SET @iQteVendu = 0
		end
	SET @iQteVendu = @iQteVendu + @iQteServie
 
	UPDATE ARTICLE
	SET NBR_VENTE_ARTICLE = @iQteVendu,
	NBR_SORTIE_ARTICLE= @iNbreVente,
	DATE_DERN_SORTIE_ARTICLE=@sDate
	WHERE ID_ARTICLE=@iIdArticle
	SET @NewNumVenteErrorChek = @@ERROR
--
SET @iMois = month(getdate())
SET @iAnnee = year(getdate())
-----------
--test si le pdt existe ds la table historique pr le mois et l'annee courante
 SET @iSomme =(SELECT count(*) FROM HISTORIQUE_ARTICLE WHERE ID_ARTICLE=@iIdArticle AND annee_historique_article=@iAnnee AND mois_historique_article=@iMois)
 IF(@iSomme>0)
--si il existe on fait la MAJ
	begin
		UPDATE historique_article
		SET NBR_VENTE_MOIS_ARTICLE = (SELECT NBR_VENTE_MOIS_ARTICLE FROM HISTORIQUE_ARTICLE WHERE ID_ARTICLE=@iIdArticle AND annee_historique_article=@iAnnee AND mois_historique_article=@iMois) + @iQteServie,
		NBR_SORTIE_MOIS_ARTICLE=  (SELECT NBR_SORTIE_MOIS_ARTICLE FROM HISTORIQUE_ARTICLE WHERE ID_ARTICLE=@iIdArticle AND annee_historique_article=@iAnnee AND mois_historique_article=@iMois) + 1
		WHERE ID_ARTICLE=@iIdArticle AND annee_historique_article=@iAnnee AND mois_historique_article=@iMois
		SET @NewNumVenteErrorChek = @@ERROR
 
		---MAJ VENTE_MOIS_ARTICLE et CONS_MOIS_ARTICLE de la table article
		SET @iVenteMois = 0
		SET @iConsommation = 0
		SET @iVenteMois = (SELECT VENTE_MOIS_ARTICLE FROM article WHERE id_article=@iIdArticle)
		IF(@iVenteMois IS NULL)
 
		begin
			SET @iVenteMois = 0
		end
		SET @iConsommation = (SELECT CONS_MOIS_ARTICLE FROM article WHERE id_article=@iIdArticle)
 
		IF(@iConsommation IS NULL)
		begin
			SET @iConsommation = 0
		end
		SET @iConsommation = @iConsommation + @iQteServie
		SET @iVenteMois = @iVenteMois + 1
-------------------------------------------------------------------------
		UPDATE article SET CONS_MOIS_ARTICLE=@iConsommation,VENTE_MOIS_ARTICLE=@iVenteMois WHERE ID_ARTICLE=@iIdArticle
		SET @NewNumVenteErrorChek = @@ERROR
-------------------------------------------------------------------------
	end 
else
	begin
		INSERT INTO historique_article(id_article,annee_historique_article,mois_historique_article,NBR_VENTE_MOIS_ARTICLE,NBR_ACHAT_MOIS_ARTICLE,NBR_SORTIE_MOIS_ARTICLE,NBR_ENTREE_MOIS_ARTICLE) VALUES(@iIdArticle,@iAnnee,@iMois,@iQteServie,0,1,0)
		SET @NewNumVenteErrorChek = @@ERROR
-------------------------------------------------------------------------
UPDATE article SET CONS_MOIS_ARTICLE=@iQteServie,
		VENTE_MOIS_ARTICLE=1,
		NBR_SORTIE_ARTICLE=@iQteServie,
		NBR_VENTE_ARTICLE=1
		 WHERE ID_ARTICLE=@iIdArticle
 
		SET @NewNumVenteErrorChek = @@ERROR
-------------------------------------------------------------------------
	end
 
----------------
		SET @NewNumVenteErrorChek = @@ERROR
		SET @iStock		= @iStock - @iQteServie
		SET @iQteReserve	= @iQteReserve - @iQteServie
 
------------------------------------------------------------------------------------------------------------------------------------------
		---------------------MAJ Stock
		--exec MAJQteReserveArticle @iIdArticle,@iQteReserve,@dPrix,1,@iStock
SET @iMAJQteStock=1
SET @iStockTotal=0
SET @iMAJUniteGratuite=0
 
/*MAJ de la Qte Reserve ds ARTICLE_STOCK et ARTICLE*/
UPDATE 
	ARTICLE_STOCK
SET
	QTE_RESERVE_ARTICLE_STOCK= @iQteReserve
 
WHERE 
	ID_ARTICLE=@iIdArticle
	AND
	PRIX_VENTE_ARTICLE_STOCK LIKE @dPrix
SET @NewNumVenteErrorChek = @@ERROR
 
UPDATE 
	ARTICLE
SET
	QTE_RESERVE_ARTICLE= (SELECT sum(QTE_RESERVE_ARTICLE_stock) FROM ARTICLE_stock WHERE ID_ARTICLE=@iIdArticle)
 
WHERE 
	ID_ARTICLE=@iIdArticle
SET @NewNumVenteErrorChek = @@ERROR	
 
/*MAJ STOCK ARTICLE STOCK*/
IF(@iMAJQteStock>0)
begin
	---insertion ds la table mouvement article
	declare @iStock1 int,
	@iQte int
		SET @iStock1 = (SELECT top 1 STOCK_ARTICLE_STOCK FROM ARTICLE_STOCK WHERE ID_ARTICLE=@iIdArticle AND PRIX_VENTE_ARTICLE_STOCK LIKE @dPrix)
		SET @iQte     = @iStock - @iStock1
		IF(@iQte!=0)
		begin
			INSERT INTO mouvement_article(date_mouvement,stock_ancien,nature_mouvement,qte_modifie,prix_vente_article,id_article) VALUES(GETUTCDATE(),@iStock1,'VENTE',@iQte,@dPrix,@iIdArticle)
			SET @NewNumVenteErrorChek = @@ERROR
		end
 
	/*MAJ de stock  de l'article */
		UPDATE
			ARTICLE_STOCK
		SET
			STOCK_ARTICLE_STOCK=@iStock,
			date_vente_article_stock = convert(varchar(50),getdate(),103)
		WHERE
			ID_ARTICLE=@iIdArticle
			AND
			PRIX_VENTE_ARTICLE_STOCK LIKE @dPrix
		SET @NewNumVenteErrorChek = @@ERROR
		IF(EXISTS(SELECT * FROM article_stock WHERE ID_ARTICLE=@iIdArticle AND PRIX_VENTE_ARTICLE_STOCK LIKE @dPrix AND suppression LIKE 'oui'))
		begin
			IF(@iStock!=0)
			begin
				UPDATE 	ARTICLE_STOCK SET suppression='NON' WHERE ID_ARTICLE=@iIdArticle AND PRIX_VENTE_ARTICLE_STOCK LIKE @dPrix
				SET @NewNumVenteErrorChek = @@ERROR
			end
		end
		UPDATE
			ARTICLE
		SET
			STOCK_TOTAL_ARTICLE=(SELECT sum(STOCK_ARTICLE_STOCK) FROM ARTICLE_STOCK WHERE ID_ARTICLE=@iIdArticle)
		WHERE
			ID_ARTICLE=@iIdArticle
		SET @NewNumVenteErrorChek = @@ERROR
		IF(@iMAJUniteGratuite!=0)
		begin
			SET @iUniteGratuitePdt = (SELECT unite_gratuite_article_stock FROM article_stock  WHERE ID_ARTICLE=@iIdArticle AND PRIX_VENTE_ARTICLE_STOCK LIKE @dPrix)
			IF(@iUniteGratuitePdt IS NULL)
			begin
				SET @iUniteGratuitePdt = 0
			end
			SET @iUniteGratuitePdt = @iUniteGratuitePdt+@iUnite
			UPDATE article_stock SET unite_gratuite_article_stock=@iUniteGratuitePdt  WHERE ID_ARTICLE=@iIdArticle AND PRIX_VENTE_ARTICLE_STOCK LIKE @dPrix
			SET @NewNumVenteErrorChek = @@ERROR
		end
 
end
------------------------------------------------------------------------------------------------------------------------------------------
SET @NewNumVenteErrorChek = @@ERROR
-----------------------------------
FETCH NEXT FROM Encours 
INTO @iIdTransVente,@iIdArticle,@dPrix,@iStock,@iQteReserve,@iQteServie,@iUnite
END
CLOSE Encours
DEALLOCATE Encours
--commit transaction
IF @NewNumVenteErrorChek = 0 
	BEGIN
		COMMIT TRANSACTION
	END
else
	BEGIN
		ROLLBACK TRANSACTION
	END


si par hasard vous sauriez où est exactement se produit ce message d'erreur .
Merci

6 réponses

blux Messages postés 26529 Date d'inscription dimanche 26 août 2001 Statut Modérateur Dernière intervention 13 décembre 2024 3 317
10 juil. 2013 à 10:44
Salut,

en dehors du fait que le code que tu colles ne sert à rien, il n'y a pas de moyen de savoir à l'avance où se produit un deadlock (dans le cas contraire, on pourrait tout faire pour empêcher sa venue).

C'est donc à toi d'intercepter l'erreur, de vérifier que le rollback a bien eu lieu et de relancer l'intégralité de ta transaction.
0
oui , le problème c'est que ce n'est pas moi qui l'ai fait ,j'ai eu l'application déjà codée, et l'utilisateur de cette application à rencontré ce message d'erreur , et à la fin c'est à moi qui dois le résoudre mais j 'ai pas su comment commencer ce script :'(
-----------------est ce que ce script peut être la cause d'un DEADLOCK,???????
0
blux Messages postés 26529 Date d'inscription dimanche 26 août 2001 Statut Modérateur Dernière intervention 13 décembre 2024 3 317
10 juil. 2013 à 13:15
Désolé, je ne connais pas SQL Server pour t'en dire plus à ce niveau...
0
non maintenant je veux juste savoir est ce que ce script peut être la cause d'un DEADLOCK ?????
0
blux Messages postés 26529 Date d'inscription dimanche 26 août 2001 Statut Modérateur Dernière intervention 13 décembre 2024 3 317
10 juil. 2013 à 16:04
Forcément, si son exécution a été stoppée par le moteur du SGBD, c'est qu'il a été impliqué dans un deadlock (impliqué ne veut pas dire qu'il en est la cause expresse).
En relançant le traitement, il est quasiment sûr que ça fonctionne...
0
quand je démarrage le traçage (sql profiler) il ne détecte rien au niveau de cette procédure
0
Morgothal Messages postés 1236 Date d'inscription jeudi 22 avril 2010 Statut Membre Dernière intervention 19 mai 2015 183
10 juil. 2013 à 15:58
Bonjour,
En regardant par exemple ce lien, peux-être pourras-tu comprendre qu'un deadlock ne se prévoit pas...
Ton script est peut-être la cause d'un deadlock.
0

Vous n’avez pas trouvé la réponse que vous recherchez ?

Posez votre question
quand je démarrage le traçage (sql profiler) il ne détecte rien au niveau de cette procédure...
0
blux Messages postés 26529 Date d'inscription dimanche 26 août 2001 Statut Modérateur Dernière intervention 13 décembre 2024 3 317
11 juil. 2013 à 08:48
Le principe du deadlock est justement de ne pas être prévisible !
Comme je l'ai dit : relance la transaction, il y a 99,999999% de chances qu'elle repasse sans problème.
0
vous avez une idée comment faire disparaître ce deadlock pare que je ne sais vraiment pas comment refaire cette procédure stockée de manière que ce phénomène ne se reproduit plus .
MERCI
0
blux Messages postés 26529 Date d'inscription dimanche 26 août 2001 Statut Modérateur Dernière intervention 13 décembre 2024 3 317
11 juil. 2013 à 12:46
On vient de te dire un certain nombre de fois que le deadlock (en conditions normales) n'est :

- ni prévisible
- ni reproductible
- ni solvable a priori

Tu pourras modifier la procédure tant que tu veux, s'il doit y avoir un deadlock, il se produira...
0
ok merciiii
0
Morgothal Messages postés 1236 Date d'inscription jeudi 22 avril 2010 Statut Membre Dernière intervention 19 mai 2015 183
11 juil. 2013 à 15:54
Tu peux exécuter ton script avec l'option WITH NO LOCK pour ne pas avoir de verrou, mais cela t'expose à plusieurs soucis potentiels...

Plus d'infos par ici...
0
c'est enfin je pense avoir trouvé la solution j 'ai testé plusieurs foi ça n'a pas donné d'erreur.
pour ceux qui veulent savoir comment :


RETRY: -- Label RETRY ----N'oubliez pas cette ligne 
BEGIN TRANSACTION
BEGIN TRY
DECLARE ...............
....... --- Ecrivez vos requêtes ici 
.......
COMMIT TRANSACTION
END TRY  
BEGIN CATCH
	PRINT 'Rollback Transaction'
	ROLLBACK TRANSACTION
	IF ERROR_NUMBER() = 1205  -- IF Deadlock Error Number
	BEGIN
		WAITFOR DELAY '00:00:00.03' -- Wait for 3 ms (LE DÉLAI C'est selon la taille de votre TRANSACTION)
		GOTO RETRY  -- Go to Label RETRY
	END
END CATCH



on met le TRY CATCH à notre TRANSACTION ,dans le TRY on met apres chaque MISE A JOUR :


WAITFOR DELAY '00:00:03'
--et N'oubliez pas aussi cette ligne

et dans le CATCH on écrit ce qui est cité au dessus.
DITES LE MOI SI C'EST RÉSOLU
0
blux Messages postés 26529 Date d'inscription dimanche 26 août 2001 Statut Modérateur Dernière intervention 13 décembre 2024 3 317
17 juil. 2013 à 21:59
Je ne connais pas cette syntaxe, mais ce que je peux dire, c'est que lorsque tu indiques que tu as testé plusieurs fois sans problème, ça n'en fait pas une garantie imparable contre les deadlocks. D'après la syntaxe, il semblerait que tu fasses un rollback puis une relance de la transaction, c'est effectivement le moyen de contourner le deadlock, mais ce n'est pas le moyen de l'éviter, puisqu'il est non prévisible...
0
oui c'est vrai , jusqu'à maintenant les utilisateurs de l'application n'ont eu aucune erreur , le problème pourra se produire si plusieurs utilisateurs font la même opération en même temps je suppose . bref j'espère que tout se passera . Merci pour votre aide :)
0
blux Messages postés 26529 Date d'inscription dimanche 26 août 2001 Statut Modérateur Dernière intervention 13 décembre 2024 3 317
18 juil. 2013 à 13:49
le problème pourra se produire si plusieurs utilisateurs font la même opération en même temps je suppose
C'est la condition nécessaire et suffisante du deadlock.
0