Je reçois beaucoup d'impasse dans ma grande application Web.
Comment ré- Exécuter une transaction deadholelite? (ASP.NET MVC / SQL Server) P>
Ici, je voulais réexécuter des transactions impressionnées, mais on m'a dit de me débarrasser des impasses - c'est bien mieux que d'essayer d'attraper le Deadlocks. P>
Alors j'ai passé toute la journée avec SQL Profiler, régler les clés de traçage, etc. Et c'est ce que j'ai eu. p>
Il y a un et ensuite il y a la requête suivante dans C'est là que je reçois l'utilisateur de cookies. P> très souvent une impasse survient et cette seconde linq-to- La requête SQL est choisie comme une victime. Ce n'est donc pas exécuté et les utilisateurs de mon site voient un écran d'erreur. P> Il s'agit de l'information du graphique .xdl capturé par SQL Profiler (c'est juste la première impasse, c'est Pas le seul. Toute la liste est gigantesque.): P> utilisateurs code> . J'ai une page d'utilisatrice très élevée avec la requête suivante (ce n'est pas la seule requête, mais c'est celui qui provoque des problèmes) p>
<deadlock-list>
<deadlock victim="process824df048">
<process-list>
<process id="process824df048" taskpriority="0" logused="0" waitresource="PAGE: 7:1:13921" waittime="1830" ownerId="91418" transactionname="SELECT" lasttranstarted="2010-05-31T12:17:37.663" XDES="0x868175e0" lockMode="S" schedulerid="2" kpid="5076" status="suspended" spid="72" sbid="0" ecid="2" priority="0" trancount="0" lastbatchstarted="2010-05-31T12:17:37.663" lastbatchcompleted="2010-05-31T12:17:37.663" clientapp=".Net SqlClient Data Provider" hostname="WIN-S41KV2CLS67" hostpid="6920" isolationlevel="read committed (2)" xactid="91418" currentdb="7" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="74" sqlhandle="0x02000000de1cb30b5b2e40e31ffb345af3c7529430b559c2">
*password------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- </frame>
<frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
</inputbuf>
</process>
<process id="process8765fb88" taskpriority="0" logused="216" waitresource="PAGE: 7:1:14196" waittime="1822" ownerId="91408" transactionname="UPDATE" lasttranstarted="2010-05-31T12:17:37.640" XDES="0x86978e90" lockMode="IX" schedulerid="2" kpid="5216" status="suspended" spid="73" sbid="0" ecid="0" priority="0" trancount="2" lastbatchstarted="2010-05-31T12:17:37.557" lastbatchcompleted="2010-05-31T12:17:37.557" clientapp=".Net SqlClient Data Provider" hostname="WIN-S41KV2CLS67" hostpid="6920" loginname="sdfkj93jks9sl" isolationlevel="read committed (2)" xactid="91408" currentdb="7" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="database.dbo.UpdateUserStats" line="31" stmtstart="1794" stmtend="2088" sqlhandle="0x03000700bac8836333e58f00879d00000100000000000000">
UPDATE Users
SET Views = Views + 1
WHERE ID IN (SELECT AuthorID FROM Articles WHERE ArticleID = @ArticleID) </frame>
<frame procname="adhoc" line="1" stmtstart="84" sqlhandle="0x01000700b7c78e0760dd3f81000000000000000000000000">
EXEC @RETURN_VALUE = [dbo].[UpdateUserStats] @UserID = @p0 </frame>
<frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
(@p0 int,@RETURN_VALUE int output)EXEC @RETURN_VALUE = [dbo].[UpdateUserStats] @UserID = @p0 </inputbuf>
</process>
<process id="process86ce0988" taskpriority="0" logused="10000" waittime="1806" schedulerid="1" kpid="2604" status="suspended" spid="72" sbid="0" ecid="0" priority="0" trancount="0" lastbatchstarted="2010-05-31T12:17:37.663" lastbatchcompleted="2010-05-31T12:17:37.663" clientapp=".Net SqlClient Data Provider" hostname="WIN-S41KV2CLS67" hostpid="6920" loginname="sdfkj93jks9sl" isolationlevel="read committed (2)" xactid="91418" currentdb="7" lockTimeout="4294967295" clientoption1="671088672" clientoption2="128056">
<executionStack>
<frame procname="adhoc" line="1" stmtstart="74" sqlhandle="0x02000000de1cb30b5b2e40e31ffb345af3c7529430b559c2">
*password------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- </frame>
<frame procname="unknown" line="1" sqlhandle="0x000000000000000000000000000000000000000000000000">
unknown </frame>
</executionStack>
<inputbuf>
*password-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- </inputbuf>
</process>
</process-list>
<resource-list>
<pagelock fileid="1" pageid="13921" dbid="7" objectname="database.dbo.Users" id="lock85535c80" mode="IX" associatedObjectId="72057594046382080">
<owner-list>
<owner id="process8765fb88" mode="IX"/>
</owner-list>
<waiter-list>
<waiter id="process824df048" mode="S" requestType="wait"/>
</waiter-list>
</pagelock>
<pagelock fileid="1" pageid="14196" dbid="7" objectname="database.dbo.Users" id="lock8469f980" mode="SIU" associatedObjectId="72057594046382080">
<owner-list>
<owner id="process86ce0988" mode="S"/>
</owner-list>
<waiter-list>
<waiter id="process8765fb88" mode="IX" requestType="convert"/>
</waiter-list>
</pagelock>
<exchangeEvent id="Pipe894b0680" WaitType="e_waitPipeGetRow" nodeId="0">
<owner-list>
<owner id="process824df048"/>
</owner-list>
<waiter-list>
<waiter id="process86ce0988"/>
</waiter-list>
</exchangeEvent>
</resource-list>
</deadlock>
3 Réponses :
Votre problème a beaucoup de parallèles avec cela ici ici Diagnostiquer des blocages dans SQL Server 2005 < / a> p>
(LINQ à SQL SQL, lecture seule transaction étant impatiente par une transaction d'écriture de lecture) p>
Si vous êtes sur SQL2005 ou plus tard peut-être installer l'isolement d'instantané comme indiqué sur ce thread fera le travail. Sinon, veuillez mettre à jour votre message avec des détails de la version que vous utilisez. P>
Dans cette situation (c'est-à-dire le type de données que vous lisez et la nature des mises à jour survenant sur ces données) Je voudrais exécuter la requête de la recherche de l'utilisateur en lecture isolation non engagée. P>
Alternativement, un changement plus impliqué. Dans la description que vous avez postée, je envisagerais de ne pas conserver les points de vue compter sur l'enregistrement d'utilisateur. Je ferais plutôt enregistrer la visitère contre l'article, puis la dervive des vues totales d'un utilisateur de la somme des articles.Viewcount par AutorID. P>
Vous devez capturer le graphique de l'impasse. Attachez le profileur et capturez le Événement graphique deadlock classe. Enregistrez le graphique .xdl et ajoutez cette information à votre message.
Jusqu'à ce que, est assez évident que votre requête DB.USERS.SINGLEORDEFAULT nécessite un indice sur le nom au moins, sinon sur nom et mot de passe: P> < PRE> XXX PRE>
Je pense que les utilisateurs disposent déjà d'un index sur ID et des articles ont un index sur l'article qui couvre également Autorid. En supposant que les utilisateurs.Id et les articles.Articleid sont des pks dans leurs tableaux respectifs, ils sont probablement la clé en regroupement de la clé respective, c'est vrai. Cela vaut la peine de vérifier, cependant. P>
et, comme je vous ai déjà répondu une fois dans votre précédent poste, vous avez décidé de passer à autre chose et de laisser non-réponse, vous devriez envisager d'allumer isolation d'instantané : p> En plus de cela, le stockage de mot de passe en texte clair est une majeure #FAIL. P> Il existe trois processus (demandes): p> Le cycle de blocage est: p> Le cycle est donc c-> a-> b-> c. p> du fait que les deux sélectionneurs impliqués de décider de 1) utilisent un plan parallèle et 2). Les serrures sont évidentes qu'ils font une analyse de bout en bout de la table des utilisateurs entière. Le problème est donc, comme je l'avais prédit, un manque d'index sur (nom, mot de passe) sur les utilisateurs qui provoque la numérisation de la requête de trop de données. L'ajout de l'index passerait la sélection en une recherche droite sur l'index NC et une recherche sur l'index en cluster, et cela réduirait considérablement la fenêtre de chevauchement avec la mise à jour. À l'heure actuelle, la mise à jour est à peu près garantie au conflit avec tout em> sélectionne, car chaque sélection est garantie de lire toutes les lignes. P> Ajout de l'index réalisera le problème immédiat. Utilisation d'une isolation d'instantané masque em> le problème, car les analyses de bout en bout vont toujours se produire à moins que l'index (nom, mot de passe) soit ajouté. Ou seulement (nom) fonctionnera probablement aussi. P> Pour une évolutivité future, la mise à jour de la colonne Vues sur chaque page de page em> ne fonctionnera pas. Mise à jour retardée, mise à jour du nombre d'agrégats de lots, partitionnez verticalement la table des utilisateurs et sortez la colonne Vues sont des alternatives viables. P> P>
Sélectionnez ... à partir des utilisateurs où mot de passe = ... et nom = ... code> li> li>
Sélectionnez ... à partir des utilisateurs où mot de passe = ... et nom = ... code> li> li>
... code> li>
ul>
Désolé, j'ai oublié d'accepter votre réponse. Oui, je vais mettre à jour le système de stockage de mot de passe. Je vais mettre à jour ma question avec .xdl info.
Merci beaucoup pour une réponse aussi détaillée! Je n'ai jamais rencontré d'indexation d'autres colonnes différentes des clés primaires. Que dois-je faire pour ajouter l'index (nom, mot de passe)? J'ai trouvé la fenêtre index / clés dans le concepteur de la table. Il a une clé pk_utilisateurs, et je peux ajouter IX_USERS KEY pour le nom d'utilisateur, mais comment puis-je l'associer au mot de passe? Merci encore.
@Alex - convenu de la qualité de la réponse. La réponse est au sommet de Remus's Post Créer index IDXUserSnamePassword sur les utilisateurs (nom, mot de passe); code> et vous trouverez peut-être ce lien utile comme point de départ pour identifier d'autres indices manquants potentiels à enquêter
Incroyable! Je viens de déposé la colonne de nom en tant qu'index unique IX, et ça ... fonctionne! Pas plus de blocage, pas un seul. Je ne sais pas comment exprimer à quel point je suis heureux. Merci les gars. J'ai l'impression d'avoir aussi besoin de contribuer et d'aider quelqu'un d'autre ici. C'est si génial qu'il y ait des gens qui sont prêts à aider gratuitement, car ils veulent juste aider.
Êtes-vous sur SQL2005 ou plus tard? Si oui, avez-vous obtenu le graphique de l'impasse du profileur SQL? Savez-vous également quel niveau d'isolement de transaction vos requêtes sont-elles sous-jacentes?
Oui j'ai le graphique. C'est là que j'ai eu cette information de. Je ne sais rien de l'isolement des transactions. Où puis-je vérifier?
Dans la trace du profileur, cliquez avec le bouton droit de la sour clé sur l'événement Graphique deadlock et choisissez Extraire des données d'événement, enregistrez-la sous XML. Puis ouvrez cela dans le bloc-notes et trouvez "isolationlevel"
Je viens de vérifier, c'est toujours "lu engagé (2)"