7
votes

J'ai des données sur les impasses, mais je ne comprends pas pourquoi ils se produisent

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 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> xxx pré>

et ensuite il y a la requête suivante dans Toutes les pages fortes>: p> xxx pré>

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>

<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>


4 commentaires

Ê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)"


3 Réponses :



1
votes

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.

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.


0 commentaires

12
votes

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: < PRE> XXX

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.

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é : xxx

En plus de cela, le stockage de mot de passe en texte clair est une majeure #FAIL.

MISE À JOUR après impression d'impression

Il existe trois processus (demandes):

  • a) ... F048 qui exécute le Sélectionnez ... à partir des utilisateurs où mot de passe = ... et nom = ...
  • b) ... 0988 qui exécute le Sélectionnez ... à partir des utilisateurs où mot de passe = ... et nom = ...
  • c) ... FB88 qui exécute la mise à jour ...

    Le cycle de blocage est:

    1. C attend la page IX verrouillage, est bloqué par la serrure de A d'A d'A
    2. B attend la page S Verrouillage, est bloqué par C Verrouillage IX de C '/ LI>
    3. une attente sur les ressources d'échange parallèle, est bloquée par B

      Le cycle est donc c-> a-> b-> c.

      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 sélectionne, car chaque sélection est garantie de lire toutes les lignes.

      Ajout de l'index réalisera le problème immédiat. Utilisation d'une isolation d'instantané masque 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.

      Pour une évolutivité future, la mise à jour de la colonne Vues sur chaque page de page 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.


4 commentaires

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); et vous trouverez peut-être ce lien utile comme point de départ pour identifier d'autres indices manquants potentiels à enquêter Blogs. msdn.com/b/bartd/archive/2007/07/19/...


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.