go backsqlschool blogs list

The SQL Server Operating System (SQLOS) – Μέρος 1ο

by Antonios Chatzipavlis

 

Πριν προχωρήσω στο αντικείμενο που θέλω να παρουσιάσω θα ήθελα να περιγράψω κάποιες γνωστές έννοιες που θεωρώ ότι είναι καλό να επαναληθούν, μιας και η επανάληψη είναι η μητέρα της μάθησης όπως έλεγαν οι πρόγονοι μας.

Κάθε application ( και με αυτό τον όρο συμπεριλαμβάνω και τα services ) μπορεί να εκτελεσθεί πολλές φορές. Κάθε εκτέλεση του application είναι ένα instance.

Κάθε instance που τρέχει είναι ένα process, το οποίο στην ουσία είναι ένας container από ένα ή πολλα threads και τα οποία είναι προγραμματισμένα να κάνουν χρήση του επεξεργαστή για ένα συγκεκριμένο χρονικό διάστημα (time slice) το οποίο είναι οριζόμενο από το λειτουργικό σύστημα.

Τα threads επιτρέπουν στην εφαρμογή να χρησιμοποιεί με το καλύτερο δυνατό τρόπο τον επεξεργαστή, είτε αυτός είναι ένας, είτε περισσότεροι.

Τα Windows είναι ένα preemptive (με προτίμηση λόγω κατοχής) multitasking (πολυεπεξεργαστικό) λειτουργικό σύστημα.

Αυτό σημαίνει ότι σε κάθε περίπτωση που τρέχουμε ένα application το λειτουργικό σύστημα δίνει ένα χρονικό διάστημα στο thread για να τρέξει. Όταν αυτό το χρονικό διάστημα περάσει ή κάποιο άλλο thread με προτεραιότητα μεγαλύτερη (high-priority) από αυτό που τρέχει την δεδομένη χρονική στιγμή, θέλει να τρέξει, τότε το λειτουργικό σύστημα αποθηκεύει την contextual information (συναφή πληροφορία) του τρέχοντος thread, το αντικαθιστά ή το σταματά και φορτώνει την contextual information από κάποιο άλλο thread ώστε αυτό να τρέξει με την σειρά του για το χρονικό διάστημα που του αναλογεί. Αυτό είναι το γνωστό σαν context switching και όλη η διαδικασία σαν Windows preemptive scheduling.

User Mode Scheduler (UMS)

Από την έκδοση 6.5 ο SQL Server χρησιμοποιεί ιδανικά το Windows scheduling. Όμως αυτό είναι γενικού σκοπού και για όλα τα application και όπως είναι φυσικό περιορίζει τo scalability (κλιμάκωση) που ο SQL Server προσπαθεί να επιτύχει. Η προσέγγιση του Windows preemptive sheduling έχει σαν αποτέλεσμα το context switching το οποίο είναι ακριβό σαν διαδικασία μιας και εναλλάσετε μεταξύ του user και του kernel mode του επεξεργαστή.

Έτσι ένα process όπως του SQL Server το οποίο δημιουργεί και χρησιμοποιεί πολλά threads η εκτεταμένη χρήση του context switching έχει αρνητική επίδραση στο γενικότερο performance αλλά και το scalability του. Αυτός είναι και ο λόγος για τον οποίο η ομάδα ανάπτυξης του SQL Server αποφάσισε ότι ο ίδιος o SQL Server πρεπει να κάνει δικό του scheduling. Έτσι ο SQL Server γνωρίζει και ορίζει καλύτερα τις δικιές του ανάγκες για scheduling από ότι το λειτουργικό. Ακόμα θα πρέπει να τονίσω ότι ο SQL Server κάνει καλύτερη υλοποίηση όσον αφορά το thread scheduling και αποφεύγει σχεδόν πάντα το context switching.

Από την έκδοση 7.0 του SQL Server παρουσιάστηκε η έννοια του User Mode Scheduler (UMS) o οποίος είναι ένα thin layer πάνω από το λειτουργικό σύστημα με πρωταρχικό σκόπο να βελτιστοποιήσει το thread management του SQL Server, ελαχιστοποιόντας το context switching και προσπαθώντας να κρατήσει όσο το δυνατόν τα SQL Server schedules στο user mode.

Έτσι στο binn folder της εγκατάστασης του SQL Server 7.0 θα βρείτε ένα αρχείο to ums.dll, το οποίο είναι η υλοποίηση του UMS.

Εδώ θα πρέπει να τονίσω ότι δεν θα γινόταν και τίποτα σπουδαίο αν το UMS εκτός από το scheduling δεν αφαιρούσε από το λειτουργικό χαρακτηριστικά που είναι system dependent όπως τα fibers και asynchronous Ι/Ο.

Αλλά για να δούμε πως το UMS καταφέρνει να επιβληθεί πάνω στο Windows scheduling;

UMS έχει την "εμπιστοσύνη" των Windows ότι όλα τα threads εκτός από αυτό που το ίδιο θέλει δεν είναι εφαρμόσιμο ("not viable"). Εαν ένα thread βρήσκεται σε ένα infinite wait state, αυτό σημαίνει ότι εάν ένα thread καλέσει την WaitForSingleObject και περάσει INFINITE σαν timeout value, τα Windows εκλαμβάνουν το thread αυτό σαν "not viable" για scheduling και το αγνοούν. Ο μόνος τρόπος για να ξυπνήσει ένα τέτοιο thread είναι στείλω ένα σήμα στο thread's event object.

Στο λειτουργικό σύστημα φαίνεται μόνο ένα SQL Server thread ανα επεξεργαστή να είναι ενεργό κάθε φορά. Έτσι ακόμα και εάν έχουμε εκατοντάδες worker threads σε μια δεδομένη χρονική στιγμή, μόνο ένα από αυτά για κάθε επεξεργαστή εμφανίζετε στα Windows να κάνει κάτι.

Ο Windows scheduler είναι όπως είπαμε preemptive. Από την άλλη μεριά ο UMS προσπαθεί και επιτυχώς ακολουθεί ένα cooperative model και είναι ένας non-preemptive scheduler.

Ο UMS βασίζεται σε αυτό που λεμε "on threads to yield voluntarily" το οποίο σε ελεύθερη μετάφραση θα το πω "στην εθελούσια παραίτηση του thread".

O UMS χρησιμοποιεί την προσέγγιση αυτή ώστε να χρησιμοποιήσει τον Windows kernel μόνο όταν είναι πραγματικά απαραίτητος.

Το UMS cooperative scheduling απαίτησε να γραφτεί τέτοιος κώδικας από το SQL Server development team που θα μου επιτραπεί να τον χαρακτηρίσω λίρα εκατό. Αλλά αυτό άξιζε τον κόπο μιας καταφέρνει να είναι πιο αποτελεσματικο από του λειτουργικού αφού είναι κομένο και ραμένο στα μέτρα του SQL Server.

Έτσι όταν ένα thread υποχωρεί είτε επειδή τελειώσε το task του είτε επειδή εκτέλεσε κώδικα που αφορούσε κλήση σε μια απο τις yield functions του UMS, αυτός ελέγχει την λίστα με τα threads τα οποία είναι έτοιμα να τρέξουν και λέει στο πρώτο διαθέσιμο οτι μπορεί να τρέξει. Έτσι με αυτό τον τρόπο όλα γίνονται στο user mode και αποφεύγεται το switching στο kernel mode.

Όταν ο SQL Server ξεκινά, για κάθε επεξεργαστή δημιουργήτε ένας UMS. Κάθε UMS συντηρεί τα ακόλουθα 5 πράγματα:

  • Worker List

Η λίστα αυτή είναι τα διαθέσιμα threads ή fibers. Ο αριθμός των διαθέσιμων threads ορίζεται από αυτόν που έχουμε ορίσει στο max worker threads option κάνοντας χρήση της sp_configure. Εαν για παράδειγμα έχουμε ορίσει το max worker threads σε 255 σε ένα σύστημα με 8 επεξεργαστές , κάθε επεξεργαστής και κατα συνέπεια κάθε UMS μπορεί να έχει 32 workers (UMS workers). Κάθε ένας UMS worker μπορεί να υποστηρίξει πολλαπλούς χρήστες ή SPIDs.

  • Runnable List

Η λίστα αυτή δείχνει τους UMS workers που είναι έτοιμοι να εκτελέσουν κάποιο υπαρκτό request. Έτσι όταν ένας UMS worker υποχωρήσει σαν αποτέλεσμα της διαδικασίας υποχώρησης που περιέγραψα πιο πάνω ελεγχετε η λίστα και δίνει σήμα στο επόμενο UMS worker να προχωρήσει με αυτό που έχει να κάνει.

  • Resource Waiter List

Όταν ένας UMS worker ζητήσει κάποιο resource το οποίο είναι δεσμευμένο από κάποιον άλλον UMS worker μπαίνει στην συγκεκριμένη λίστα οικιοθελώς και μπαίνει σε infinite wait state. Όταν ο UMS worker που έχει το δεσμευμένο resource είναι έτοιμος να το αποδεσμεύσει, κοιτάζει την συγκεκριμένη λίστα και βρήσκει τον πρώτο διαθέσιμο UMS worker που ενδιαφέρεται για το συγκεκριμένο resource τον μεταφέρει στην Runnable List και «ξυπνάει» τον πρώτο διαθέσιμο UMS worker της Runnable List.

  • I/O List

Είναι η λίστα με τα outstanding asynchronous I/O requests.

  • Timer List

Είναι η λίστα με τα UMS timer request η οποία στην ουσία λέει πόσο χρόνο θα περιμένω ένα resource μέχρι να γίνει time out.

Στον SQL Server 7.0 & 2000, μπορείς να χρησιμοποιήσεις τo DBCC SQLPERF(umsstats) undocumented statement για να κάνεις monitor κάθε visible UMS στο σύστημα σου.

Στον SQL Server 2005 & 2008, μπορείς να χρησιμοποιήσεις την sys.dm_os_schedulers dynamic management view (DMV) για να δεις statistics για τους visible αλλά και για τους hidden schedulers στο σύστημα σου. Για περισσότερες λεπτομέρειες σχετικά με την DMV δείτε στο books online του SQL Server

Τί είναι το SQLOS;

Όπως είδαμε το UMS thread management έδωσε την δυνατότητα στον SQL Server να είναι self-managed και εύκολα μπορεί να γίνει scale εάν ένας νέος επεξεργαστής προστεθεί στο σύστημα μας. Από την έκδοση 7.0 του SQL Server όπου για πρώτη φορά παρουσιάσθηκε ο UMS πολλά εσωτερικά engines όπως , ο memory manager, το storage engine, και το relational engine έγιναν upgrade με built-in adaptive algorithms και self-tuning capabilities. Αυτό έδωσε την δυνατότητα στον SQL Server 7.0 όταν βγήκε στην αγορά το 1998 να είναι το πρώτο enterprise database engine το οποίο ήταν δυνατόν να κάνει automatic configuration και dynamic self-tuning.

Στον SQL Server 2005 η Microsoft πήγε το self-managing και το self-tuning σε ακόμα υψηλότερο επίπεδο. Αυτό είχε σαν αποτέλεσμα ένα νέο component το SQLOS να γεννηθεί..

Το SQLOS είναι ένα layer το οποίο κάθεται πάνω από το λειτουργικό και είναι υπεύθυνο για την διαχείριση των πόρων του λειτουργικού συστήματος που είναι όμως για τον SQL Server.

To SQLOS δίνει στον SQL Server την δυνατότητα να εξυπηρετεί τις εσωτερικές του ανάγκες για πόρους καλύτερα και σε μεγαλύτερο εύρος.

Κάθε component μέσα στο SQLOS είναι έτσι φτιαχμένο ώστε να κάνει κάποιο συγκεκριμένη εργασία καθώς επίσης να συνεργάζεται ομαλά με όλα τα άλλα componets του SQLOS, ώστε να δίνεται ένα large-scale performance προσαρμοζόμενο φυσικά σε διαφορετικά hardware configurations, όπως 32-bit, 64-bit, x64, dual core chips, και large memory addressability.

Με άλλα λόγια δεν χρειάζεται να γίνουν αλλαγές στο SQL Server configuration ώστε να γίνει το SQLOS adapt to hardware resources ενώ από την άλλη παρέχει ένα άνευ προηγουμένου scalability.

Εδώ θα πρέπει να επισημάνω ότι στον SQL Server 2005 δεν υπάρχει το ums.dll μιας και αυτό είναι ένα από τα components του SQLOS και αναφέρεται πλέον σαν "Non Preemptive Scheduler"

Όπως βλέπουμε στην παραπάνω είκόνα υπάρχουν δύο μεγάλα components του SQLOS το non-preemptive scheduling (το γνωστό UMS) και το memory management. Υπάρχουν όμως και άλλα components όπως το resource monitor, ο exception handler, και τα hosting subsystems. Το SQLOS παντρεύει όλα αυτά τα system components και δίνει την δυνατότητα ένος συνεκτικού API που δίνει την δυνατότητα στο SQL Server development team εύκολα να εκμεταλλευθεί τα χαρακτηριστικά του hardware και του λειτουργικού συστήματος.

Non-Preemptive Scheduling

Το non-preemptive scheduling component του SQLOS χρησιμοποιήτε για να κάνει scheduling και synchronizing τα concurrent tasks χωρίς να χρειασθεί να κάνει κλήση στο Windows kernel. Είναι υπεύθυνο για το ιδανικό scheduling των Windows threads ή των fibers.

Ο scheduler είναι υπέθυνος για την διαχείριση των scheduling process και διασφαλίζει οτι μόνο ένα thread processor είναι ενεργό σε κάθε δεδομένη χρονική στιγμή.

Η sys.dm_os_schedulers DMV είναι αυτή που δείχνει την λίστα των schedulers.

Ένα collection από schedulers το οποίο παρέχει ένα abstraction layer πάνω από ένα group επεξεργαστών ονομάζεται scheduling node. Με τον όρο αυτός αναφερόμαστε σε ένα unit of work το οποίο είναι scheduled από τον SQL Server.

Ένα Transact-SQL (T-SQL) statement batch μπορεί να δείχνει σε ένα ή περισσότερα tasks.

Για παράδειγμα ένα parallel query εκτελείται με πολλαπλά tasks, τα οποία εκτελούνται μέσω worker threads.

Ένα worker thread αντιπροσωπεύει ένα logical thread στον SQL Server το οποίο εσωτερικά αντιστοιχίζεται (1:1) είτε σε ένα Windows thread είτα σε fiber (εαν έχω ενεργοποιήσει το lightweight pooling στον SQL Server).

H αντιστοιχία του worker thread σε Windows thread υπάρχει μέχρι το worker thread να γινει deallocated ή επειδή υπάρχει έλειψη μνήμης ή είναι idle για μεγάλο χρονικό διάστημα. Τα Worker threads εκτελούνται και διαχειρίζονται από τα system threads.

The max worker threads Option

Κάθε instance του SQL Server συντηρεί ένα pool από Windows threads ή fibers με σκοπό να κάνει processing τα user queries. Αυτό το thread pool βοηθάει στο να γίνει optimize το performance όταν ένας μεγάλος αριθμός από clients είναι συνδεδεμένοι στον server. Το maximum size του pool αυτού ορίζεται από το max worker threads στα server configuration option.

Η minimum και τα default values για το max worker threads option (το οποίο για να μην ξεχάσω είναι στα advanced options) έχει αλλάξει στον SQL Server 2005.

Στον Server 2000 η minimum τιμή που μπορούσες να ορίσεις είναι 32, στον SQL Server 2005 είναι 128.

Στον SQL Server 2000 η default τιμή είναι 255, στον SQL Server 2005 είναι 0. Αυτό σημαίνει ότι μόνος του ο SQL Server θα κάνει αυτόματα configure τον αριθμό των worker threads κατα το startup του service. Εάν είναι 0 τότε ο SQL Server 2005 χρησιμοποιεί την παρακάτω formula ανάλογα με το είμαι σε x32 ή x64 πλατφόρμα.

Η formula είναι

# of CPUs

x32

x64

<=4

256

512

>4

256 + ( (#CPUs - 4) * 8 )

512 + ( (#CPUs – 4) * 8 )

Ενδεικτικά αναφέρω 

Number of CPUs

32-bit computer

64-bit computer

<= 4 processors

256

512

8 processors

288

576

16 processors

352

704

32 processors

480

960

Εδώ είναι θεωρώ σημαντικό να αναφέρω ότι ο SQL Server στην πραγματικότητα δεν δημιουργεί όλα τα threads αλλα δεσμεύει την μνήμη που χρειάζεται για την δημιουργία του αριθμού των threads που έχουν ορισθεί με την max worker threads.

Εαν τώρα ο αριθμός των χρηστών που είναι συνδεδεμένος την δεδομένη χρονική στιγμή είναι μικρότερος από τον αριθμός που έχει ορισθεί στην max worker threads τότε ένα thread κάνει handle ένα user connection (1:1). Εάν είναι μεγαλύτερος τότε ο SQL Server κάνει pooling ώστε το επόμενο διαθέσιμο worker thread να ικανοποιήσει το request.

Routing Tasks to a Scheduler

O SQL Server 2000 χρησιμοποιούσε για τον scheduler τον αλγόριθμο round-robin κατά την στιγμή του connection. Έτσι όλα τα batches στο ίδιο connection τρέχαν στον ίδιο scheduler, αυτό όπως γίνεται κατανοητό μπορούσε να οδηγήσει σε αστάθεια ιδιαίτερα με τα long-lived connections.

Στον SQL Server 2005, η απόφαση για την επιλογή του scheduler βασίζεται στο πόσο απασχολημένος είναι αυτός.

Με άλλα λόγια ένα task στον SQL Server 2000 πήγαινε πάντα σε έναν συγκεκριμένο scheduler, στον SQL Server 2005, η επιλογή για το σε ποιον θα πάει το task γίνεται με το ποσο φορτωμένος είναι.

Κατά τη στιγμή του connection o SQL Server 2005 διαλέγει τον λιγότερο φορτωμένο scheduler. Στο επόμενο batch στο ίδιο connection χρησιμοποιεί τον ίδιο αλογόριθμο έτσι εαν ο τρεχων scheduler είναι ο ποιο φορτωμένος διαλέγει το λιγότερο φορτωμένο.

Τα πεδία όπως το load_factor και runnable_tasks_count της sys.dm_os_schedulers μπορουν να χρησιμοποιηθούν για την εύρεση του πόσο απασχολημένος είναι ένας scheduler.

Συνεχίζεται…

Ημερομηνία: 30 June 2009 18:47
Αξιολόγηση:
Κατηγορίες:
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