Για ακόμα μια φορά θα πρέπει να ασχοληθούμε με το transaction log. Καθημερινά αντιμετωπίζω περιστατικά τα οποία μου δείχνουν ότι υπάρχει θέμα κατανόησης με την αξία, την λειτουργία αλλά και την χρήση του transaction log. Η βασική ερώτηση που μου έχει τεθεί αρκετές φορές και έχω γράφει αρκετά άρθρα για αυτή είναι γνωστή πλέον και αφορά το μέγεθος του transaction log file. Αν έχετε έρθει για πρώτη φορά στο blog αυτό μια απλή αναζήτηση εδώ θα σας φέρει αρκετά άρθρα για το θέμα αυτό. Αλλά αν ψάξετε και στον internet θα βρείτε ακόμα περισσότερα.
Αρκετές φορές έχω περιγράψει την φυσική δομή μιας βάσης τόσο μέσα από τα μαθήματα που κάνω όσο και από εδώ ή τα SQL Server Saturday Nights. Σε όλες αυτές τις περιπτώσεις έχω τονίσει ότι το transaction log εσωτερικά δομείται σε virtual log files (VLFs). Επίσης αρκετές φορές έχω αναφέρει ότι το transaction log γίνεται truncate μόνο όταν παίρνουμε transaction log backup (εφόσον είμαστε σε full ή bulk recovery model). Και ακόμα αρκετές φορές έχω αναφέρει ότι σε αυτή την περίπτωση γίνεται truncate το μη ενεργό κομμάτι αυτού το ή τα οποίο(α) δεν είναι άλλο(α) από τα VLFs που δεν έχουν ενεργό(α) transaction(s).
Για όσους λοιπόν αναρωτιούνται τι γίνεται με το transaction log τους και πώς θα συμπεριφερθεί στο επόμενο transaction log backup ή ακόμα καλύτερα θέλουν να βάλουν το δάκτυλο επί τον τύπο τον ήλο, υπάρχει ένα undocumented αλλά ευρέως γνωστό και φυσικά χρησιμοποιούμενο dbcc command και δεν είναι άλλο από το DBCC LOGINFO.
Το command αυτό μας δίνει πληροφορίες για τα VLFs που υπάρχουν μέσα στο transaction log της βάσης μας
Η εκτέλεση του είναι αρκετά απλή καθώς η μόνη παράμετρος που παίρνει το όνομα της βάσης.
dbcc loginfo (AdventureWorks2008R2)
Το αποτέλεσμα που βγάζει έχει την παρακάτω μορφή
FileId FileSize StartOffset FSeqNo Status Parity CreateLSN
----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
2 458752 8192 46 2 64 0
2 458752 466944 43 0 128 0
2 458752 925696 44 0 128 0
2 712704 1384448 45 0 128 0
Ας δούμε όμως λίγο τι είναι το κάθε πεδίο που μας εμφανίζεται από την εκτέλεση της dbcc loginfo.
-
FileID : To ID του αρχείου στην συγκεκριμένη βάση
-
FileSize : Το μέγεθος του VLF σε bytes
-
StartOffset : Το σημείο αρχής του VLF
-
FSeqNo : Το sequence number του VLF
-
Status: Η κατάσταση του VLF 0=Inactive, 2=Active
-
Parity : Parity info για το VLF
-
CreateLSN : To Log Sequence Number με το οποίο ξεκινάει το VLF
Ας δούμε λίγο τα πράγματα με ένα απλό παράδειγμα
Δημιουργώ μια βάση
use master
go
create database DemoDB
on primary
( name='demodb_data',
filename='c:\temp\demodb_data.mdf',
size=10MB
)
log on
( name='demodb_log',
filename='c:\temp\demodb_log.ldf',
size=5MB
)
go
Με αυτό έχω φτιάξει μια βάση με μέγεθος data file 10MB και log file 5ΜΒ
Εκτελώ την dbcc loginfo (demodb) και έχω το εξής
FileId FileSize StartOffset FSeqNo Status Parity CreateLSN
----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
2 1245184 8192 28 2 64 0
2 1245184 1253376 0 0 0 0
2 1245184 2498560 0 0 0 0
2 1499136 3743744 0 0 0 0
Από το αποτέλεσμα καταλαβαίνω ότι έχω ένα transaction log το οποίο έχει τέσσερα VLFs, από τα οποία χρησιμοποιείται το πρώτο καθώς το Status=2. Το μέγεθος των VLFs είναι περίπου 1,2 ΜΒ.
Δημιουργώ έναν πίνακα
create table T
( id int identity(1,1) primary key,
data char(8000) default 'abcdefghijklmnopqrstuvwxyz'
)
go
Και τον γεμίζω με 1000 εγγραφές
insert into T default values
go 1000
Εκτελώντας την DBCC LOGINFO έχω το εξής αποτέλεσμα
FileId FileSize StartOffset FSeqNo Status Parity CreateLSN
----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
2 1245184 8192 32 0 128 0
2 1245184 1253376 33 0 128 0
2 1245184 2498560 34 2 128 0
2 1499136 3743744 35 2 128 0
Παρατηρόντας το βλέπουμε ότι έχουν γεμίζει σειριακά το VLFs (FSeqNo) και ότι τα ενεργά είναι τα δύο τελευταία (Status=2).
Αν κάνω checkpoint και μετά δω ξανά το log με την dbcc θα έχω το εξής αποτέλεσμα
FileId FileSize StartOffset FSeqNo Status Parity CreateLSN
----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
2 1245184 8192 32 0 128 0
2 1245184 1253376 33 0 128 0
2 1245184 2498560 34 0 128 0
2 1499136 3743744 35 2 128 0
Παρατηρώ ότι μόνο το τελευταίο VLF είναι πλεόν ενεργό
Βάζω ακόμα 1000 εγγραφές στον πίνακα μου και έχω το εξής αποτελεσμα μετά από την εκτέλεση της dbcc
FileId FileSize StartOffset FSeqNo Status Parity CreateLSN
----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
2 1245184 8192 40 0 128 0
2 1245184 1253376 41 2 128 0
2 1245184 2498560 42 2 128 0
2 1499136 3743744 39 0 64 0
Παρατηρώ ότι τα δύο μεσαία είναι ενεργά. Παίρνω το πρώτο full backup και το πρώτο log backup
backup database demodb to disk='c:\temp\demodb.bak'
go
backup log demodb to disk='c:\temp\demodb.bak'
go
Eκτελώ την dbcc το αποτέλεσμα είναι το παρακάτω
FileId FileSize StartOffset FSeqNo Status Parity CreateLSN
----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
2 1245184 8192 40 0 128 0
2 1245184 1253376 41 0 128 0
2 1245184 2498560 42 2 128 0
2 1499136 3743744 39 0 64 0
Βάζω μια εγγραφή που δεν την κάνω commit στο transaction
BEGIN TRAN
insert into T default values
και παράλληλα από ένα άλλο session βάζω ακόμα 1000 εγγραφές, εκτελώ την dbcc από την οποία έχω το εξής απότελεσμα
FileId FileSize StartOffset FSeqNo Status Parity CreateLSN
----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
2 1245184 8192 44 2 64 0
2 1245184 1253376 45 2 64 0
2 1245184 2498560 42 2 128 0
2 1499136 3743744 43 2 128 0
2 253952 5242880 46 2 64 45000000203100009
2 270336 5496832 47 2 64 45000000203100009
2 253952 5767168 48 2 64 47000000014000009
2 335872 6021120 49 2 64 47000000014000009
2 253952 6356992 50 2 64 49000000026900009
2 401408 6610944 51 2 64 49000000026900009
2 253952 7012352 52 2 64 51000000038300009
2 466944 7266304 53 2 64 51000000038300009
2 253952 7733248 54 2 64 53000000052200013
2 253952 7987200 55 2 64 53000000052200013
2 278528 8241152 56 2 64 53000000052200013
2 253952 8519680 57 2 64 56000000014100015
2 253952 8773632 58 2 64 56000000014100015
2 344064 9027584 59 2 64 56000000014100015
2 253952 9371648 60 2 64 59000000028700003
2 253952 9625600 61 2 64 59000000028700003
2 475136 9879552 62 2 64 59000000028700003
2 253952 10354688 63 2 64 62000000054000009
2 253952 10608640 0 0 0 62000000054000009
2 253952 10862592 0 0 0 62000000054000009
2 286720 11116544 0 0 0 62000000054000009
Χωρίς άλλη σκέψη παίρνω transaction log backup και εκτελώ την dbcc
FileId FileSize StartOffset FSeqNo Status Parity CreateLSN
----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
2 1245184 8192 44 2 64 0
2 1245184 1253376 45 2 64 0
2 1245184 2498560 42 2 128 0
2 1499136 3743744 43 2 128 0
2 253952 5242880 46 2 64 45000000203100009
2 270336 5496832 47 2 64 45000000203100009
2 253952 5767168 48 2 64 47000000014000009
2 335872 6021120 49 2 64 47000000014000009
2 253952 6356992 50 2 64 49000000026900009
2 401408 6610944 51 2 64 49000000026900009
2 253952 7012352 52 2 64 51000000038300009
2 466944 7266304 53 2 64 51000000038300009
2 253952 7733248 54 2 64 53000000052200013
2 253952 7987200 55 2 64 53000000052200013
2 278528 8241152 56 2 64 53000000052200013
2 253952 8519680 57 2 64 56000000014100015
2 253952 8773632 58 2 64 56000000014100015
2 344064 9027584 59 2 64 56000000014100015
2 253952 9371648 60 2 64 59000000028700003
2 253952 9625600 61 2 64 59000000028700003
2 475136 9879552 62 2 64 59000000028700003
2 253952 10354688 63 2 64 62000000054000009
2 253952 10608640 0 0 0 62000000054000009
2 253952 10862592 0 0 0 62000000054000009
2 286720 11116544 0 0 0 62000000054000009
Κανω commit το transaction που είχα αφήσει πριν και ξαναπαίρνω log backup και εκτελώ την dbcc
FileId FileSize StartOffset FSeqNo Status Parity CreateLSN
----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
2 1245184 8192 44 0 64 0
2 1245184 1253376 45 0 64 0
2 1245184 2498560 42 0 128 0
2 1499136 3743744 43 0 128 0
2 253952 5242880 46 0 64 45000000203100009
2 270336 5496832 47 0 64 45000000203100009
2 253952 5767168 48 0 64 47000000014000009
2 335872 6021120 49 0 64 47000000014000009
2 253952 6356992 50 0 64 49000000026900009
2 401408 6610944 51 0 64 49000000026900009
2 253952 7012352 52 0 64 51000000038300009
2 466944 7266304 53 0 64 51000000038300009
2 253952 7733248 54 0 64 53000000052200013
2 253952 7987200 55 0 64 53000000052200013
2 278528 8241152 56 0 64 53000000052200013
2 253952 8519680 57 0 64 56000000014100015
2 253952 8773632 58 0 64 56000000014100015
2 344064 9027584 59 0 64 56000000014100015
2 253952 9371648 60 0 64 59000000028700003
2 253952 9625600 61 0 64 59000000028700003
2 475136 9879552 62 0 64 59000000028700003
2 253952 10354688 63 2 64 62000000054000009
2 253952 10608640 0 0 0 62000000054000009
2 253952 10862592 0 0 0 62000000054000009
2 286720 11116544 0 0 0 62000000054000009
Βάζω ακόμα 1000 εγγραφές και εκτελώ την dbcc
FileId FileSize StartOffset FSeqNo Status Parity CreateLSN
----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
2 1245184 8192 69 2 128 0
2 1245184 1253376 70 2 128 0
2 1245184 2498560 67 2 64 0
2 1499136 3743744 68 2 64 0
2 253952 5242880 71 2 128 45000000203100009
2 270336 5496832 72 2 128 45000000203100009
2 253952 5767168 73 2 128 47000000014000009
2 335872 6021120 74 2 128 47000000014000009
2 253952 6356992 75 2 128 49000000026900009
2 401408 6610944 76 2 128 49000000026900009
2 253952 7012352 77 2 128 51000000038300009
2 466944 7266304 78 2 128 51000000038300009
2 253952 7733248 79 2 128 53000000052200013
2 253952 7987200 80 2 128 53000000052200013
2 278528 8241152 81 2 128 53000000052200013
2 253952 8519680 82 2 128 56000000014100015
2 253952 8773632 58 0 64 56000000014100015
2 344064 9027584 59 0 64 56000000014100015
2 253952 9371648 60 0 64 59000000028700003
2 253952 9625600 61 0 64 59000000028700003
2 475136 9879552 62 0 64 59000000028700003
2 253952 10354688 63 2 64 62000000054000009
2 253952 10608640 64 2 64 62000000054000009
2 253952 10862592 65 2 64 62000000054000009
2 286720 11116544 66 2 64 62000000054000009
Από όλα τα παραπάνω βλέπω παρατηρώντας τα FSeqNo και Status ποια VLF είναι ενεργά και ποια όχι έτσι βλέπω πως γίνεται η ανακύκλωση του transaction log εσωτερικά και ποια είναι αυτά το VLFs τα οποία έχουν γίνει truncate.
Αυτό μου είναι χρήσιμο ακόμα όταν θέλω να κάνω shrink το log file καθώς όπως έχουμε πει αρκετές φορές για να γίνει shrink θα πρέπει τα μην ενεργά VLFs να είναι στο τέλος όχι όπως στο παραπάνω δείγμα όπου αν είμαι σε αυτή την περίπτωση θα πρέπει να παίρνω ανεπάληλα transaction log backups ώστε να φτάσω σε μια μορφή όπως αυτή
FileId FileSize StartOffset FSeqNo Status Parity CreateLSN
----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
2 1245184 8192 44 2 64 0
2 1245184 1253376 45 2 64 0
2 1245184 2498560 42 2 128 0
2 1499136 3743744 43 2 128 0
2 253952 5242880 46 2 64 45000000203100009
2 270336 5496832 47 2 64 45000000203100009
2 253952 5767168 48 2 64 47000000014000009
2 335872 6021120 49 2 64 47000000014000009
2 253952 6356992 50 2 64 49000000026900009
2 401408 6610944 51 2 64 49000000026900009
2 253952 7012352 52 2 64 51000000038300009
2 466944 7266304 53 2 64 51000000038300009
2 253952 7733248 54 2 64 53000000052200013
2 253952 7987200 55 2 64 53000000052200013
2 278528 8241152 56 2 64 53000000052200013
2 253952 8519680 57 2 64 56000000014100015
2 253952 8773632 58 2 64 56000000014100015
2 344064 9027584 59 2 64 56000000014100015
2 253952 9371648 60 2 64 59000000028700003
2 253952 9625600 61 2 64 59000000028700003
2 475136 9879552 62 2 64 59000000028700003
2 253952 10354688 63 2 64 62000000054000009
2 253952 10608640 0 0 0 62000000054000009
2 253952 10862592 0 0 0 62000000054000009
2 286720 11116544 0 0 0 62000000054000009
SQL Server ‘Denali’
Επειδή αρκετοί από εσάς φαντάζομαι ότι ήδη έχετε αρχίσει και βλέπετε την επόμενη έκδοση του SQL Server με την κωδική ονομασία Denali, πιθανότατα να έχετε εκτελέσει ή να εκτελέσετε την dbcc αυτή. Σε κάθε περίπτωση θα βρεθείτε σε μια έκπληξη καθώς σε αυτή υπάρχει νέα κολώνα και δεν είναι άλλη από την πρώτη με την ονομασία RecoveryUnitID όπου σε όλες τις γραμμές που θα εμφανιστούν έχει την τιμή μηδέν (0). Για την ενημέρωση σας χωρίς να έχω την εξουσιοδότηση να μπω σε περισσότερες λεπτομέρειες λόγω NDA, η κολώνα αυτή θα έχει πρακτική αξία στην μετά Denali έκδοση του SQL Server.
RecoveryUnitId FileId FileSize StartOffset FSeqNo Status Parity CreateLSN
-------------- ----------- -------------------- -------------------- ----------- ----------- ------ ---------------------------------------
0 2 253952 8192 49 2 128 0
0 2 253952 262144 44 0 64 0
0 2 270336 516096 45 0 64 43000000003000331
0 2 262144 786432 46 0 64 44000000013600398
0 2 262144 1048576 47 0 64 44000000038000359
0 2 262144 1310720 48 0 64 45000000025400069