go backsqlschool blogs list

Intra-query parallelism deadlock

by Antonios Chatzipavlis

Το τελευταίο καιρό ασχολούμαι με την υποδομή ενός μεγάλου πελάτη με σκοπό το optimization και φυσικά τo performance.

Μέσα στο διάστημα αυτό έχουμε κάνει αρκετές αλλαγές που οδήγησαν τα πράγματα στο σωστό δρόμο. Μια όμως από αυτές τις αλλαγές ενώ αρχικά δούλευε όπως είχε σχεδιαστεί μετά από μερικές μέρες άρχισε να εμφανίζει σε τυχαία διαστήματα συμπτώματα deadlock.

Εννοείται ότι κάτι τέτοιο δεν το αφήνεις να περάσει χωρίς να το ερευνήσεις.

Analyzing deadlock graph

Βλέποντας το deadlock graph (δείτε το άρθρο μου αυτό για το πως μπορείτε να πάρετε εύκολα το deadlock graph) είχα την παρακάτω εικόνα που ξεφεύγει από τα συνηθισμένα.

deadlock graph

To graph έδειχνε αρκετά αλλά παρόλα αυτά όμως μου ήταν δύσκολο να καταλάβω ακριβώς τι συμβαίνει. Οπότε κατέφυγα στο διάβασμα του xml που παράγει το deadlock graph και το οποίο περιέχει περισσότερες πληροφορίες και αφού πρώτα έκανα ένα φρεσκάρισμα διαβάζοντας από τα BOL το τι δίνει το xml deadlock report.

Από αυτό δείχνω παρακάτω μόνο αυτά που έχουν σημασία για την κατανόηση του προβλήματος

<deadlock>
  <victim-list>
    <victimProcess id="process314c074cf8" />
  </victim-list>
  <process-list>
    <process id="process314c074cf8" waitresource="PAGE: 9:1:810905 " schedulerid="1" kpid="14688" status="suspended" spid="229" sbid="0" ecid="5" ...
    <process id="process456be51868" waitresource="PAGE: 9:1:810905 " schedulerid="10" kpid="27244" status="suspended" spid="96" sbid="0" ecid="7" ... 
    <process id="process314c074928" schedulerid="1" kpid="19956" status="suspended" spid="229" sbid="0" ecid="9" ...
    <process id="process2dbbc38" schedulerid="1" kpid="17532" status="suspended" spid="229" sbid="0" ecid="0" ...
  </process-list>
  <resource-list>
    <pagelock fileid="1" pageid="810905" dbid="9" subresource="FULL" objectname="XXXXXXXX" id="lock15f43f0b00" mode="U" associatedObjectId="72057630202331136">
      <owner-list>
        <owner id="process456be51868" mode="U" requestType="wait" />
      </owner-list>
      <waiter-list>
        <waiter id="process314c074cf8" mode="U" requestType="wait" />
      </waiter-list>
    </pagelock>
    <pagelock fileid="1" pageid="810905" dbid="9" subresource="FULL" objectname="XXXX" id="lock15f43f0b00" mode="U" associatedObjectId="72057630202331136">
      <owner-list>
        <owner id="process2dbbc38" mode="U" />
     </owner-list>
      <waiter-list>
        <waiter id="process456be51868" mode="U" requestType="wait" />
      </waiter-list>
    </pagelock>
    <exchangeEvent id="Pipe39b93bfa00" WaitType="e_waitPipeGetRow" nodeId="35">
      <owner-list>
        <owner id="process314c074cf8" />
      </owner-list>
      <waiter-list>
        <waiter id="process314c074928" />
      </waiter-list>
    </exchangeEvent>
    <exchangeEvent id="Porta3c7ef1500" WaitType="e_waitPortOpen" nodeId="7">
      <owner-list>
        <owner id="process314c074928" />
      </owner-list>
      <waiter-list>
        <waiter id="process2dbbc38" />
      </waiter-list>
    </exchangeEvent>
  </resource-list>
</deadlock>

Αν παρατηρήσουμε στο process-list τα processes θα δούμε ότι τρία από αυτά έχουν το ίδιο session id (spid="229").

Αυτά έχουν διαφορετικό schedulerid το ίδιο system batch id (sbid="0") και διαφορετικό execution context id (ecid) πράγμα που σημαίνει ότι το συγκεκριμένο statement (update με join στην περίπτωση μου) έχει παραλληλίσει για αυτό και υπάρχουν τα exchange events στο deadlock graph.

Αναλύοντας το section του resource-list επιβεβαίωσα αυτό που αρχικά δεν είχα δει με την πρώτη ματιά και που ήταν στην ουσία ότι το συγκεκριμένο statement αυτό-μπλοκαριζόταν καθώς κάποιο από τα threads που είχαν δημιουργηθεί εξαιτίας του παραλληλισμού διάβαζε περισσότερα data σε σχέση με τα άλλα με αποτέλεσμα το deadlock.

Σε αυτές τι περιπτώσεις ο SQL Server βγάζει το εξής λάθος

Msg 8650, Level 13, State 1, Line 1 Intra-query parallelism caused your server command (process ID #??) to deadlock. Rerun the query without intra-query parallelism by using the query hint option (maxdop 1).

Το οποίο όμως δυστυχώς δεν το κάνει log στα SQL Server Logs αλλά το δείχνει μόνο στο application το οποίο όμως δεν το έκανε σωστά log και έτσι το χάναμε.

My solution

Για την επίλυση του προβλήματος όμως δεν είναι πάντα ιδανικό αυτό που προτείνει το συγκεκριμένο error message καθώς θα καθυστερεί περισσότερο η διαδικασία. Αναλύοντας το statement αποφάσισα ότι ένας POC Index στα πεδία που εμπλέκονται στο statement ήταν η καλύτερη λύση και έτσι πλέον δεν παραλληλίζει το update μου εξαιτίας του join με τους άλλους πίνακες που εμπλέκονταν σε αυτό.



//antonch


Ημερομηνία: 08 May 2017 14:02
Αξιολόγηση: ( 1 )
Κατηγορίες:
Tags:
Share it:

Αφήστε το σχόλιο σας - Leave your comment

Τα σχόλια έχουν κλείσει.
Επιτρέπονται μόνο τα σχόλια από τα μέλη του SqlSchool.gr.


newsletter subscription

Εάν επιθυμείτε να λαμβάνετε ενημέρωση από εμάς, δώστε μας το e-mail σας.
PASS chapter logo
Official Professional Association for SQL Server (PASS) chapter for Greece
Join to PASS