Deadlock
Kagami
-
blux Messages postés 27121 Date d'inscription Statut Modérateur Dernière intervention -
blux Messages postés 27121 Date d'inscription Statut Modérateur Dernière intervention -
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 :
si par hasard vous sauriez où est exactement se produit ce message d'erreur .
Merci
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
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.
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.
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,???????
-----------------est ce que ce script peut être la cause d'un DEADLOCK,???????
non maintenant je veux juste savoir est ce que ce script peut être la cause d'un DEADLOCK ?????
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.
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.
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...
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...
Plus d'infos par ici...
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 :
on met le TRY CATCH à notre TRANSACTION ,dans le TRY on met apres chaque MISE A JOUR :
et dans le CATCH on écrit ce qui est cité au dessus.
DITES LE MOI SI C'EST RÉSOLU
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
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...