Πώς κάνουμε restore συγκεκριμένο μόνο page στον SQL Server

Πώς κάνουμε restore συγκεκριμένο μόνο page στον SQL Server
Πώς κάνουμε restore συγκεκριμένο μόνο page στον SQL Server

Στο άρθρο θα αναλύσουμε τι μπορούμε να κάνουμε στη περίπτωση page corruption στον SQL Server. Υπάρχει δυνατότητα να γίνει restore μόνο το συγκεκριμένο page και να γλιτώσουμε το restore ολόκληρης της βάσης μέσα από τα backup που έχουμε (αρκεί η βάση να είναι σε full recovery model).

Τα αρχικά δεδομένα μας

Έχουμε φτιάξει τον πίνακα με όνομα “pinakas” στη βάση “db_test” και έχει περασμένες αρκετές εγγραφές που είναι γραμμένες σε διάφορα pages:

select * from db_test..pinakas
Πώς κάνουμε restore συγκεκριμένο μόνο page στον SQL Server

Ας πάρουμε ένα full backup, αν είχαμε κάποιο παλαιότερο μπορούσαμε να χρησιμοποιήσουμε και αυτό:

BACKUP DATABASE [db_test]
 TO  DISK = N'C:\backups\db_test_full.bak' WITH INIT
, COMPRESSION,  STATS = 10
GO
Σε ποια pages είναι αποθηκευμένα τα δεδομένα του πίνακα
DBCC IND(db_test, pinakas, -1)
Πώς κάνουμε restore συγκεκριμένο μόνο page στον SQL Server
Πώς βλέπουμε τι ακριβώς είναι αποθηκευμένο μέσα στο page
dbcc traceon(3604)
dbcc page(db_test,1,392,3) with tableresults
Πώς κάνουμε restore συγκεκριμένο μόνο page στον SQL Server
Ώρα να κάνουμε μόνοι μας corrupt σε page του πίνακα

Με την εντολή DBCC WRITEPAGE θα προκαλέσουμε το corrupt μας με τα στοιχεία που έχομε από το προηγούμενο query αλλάζοντας συμπληρώνοντας το όνομα της βάσεις και τον αριθμό του page (στο παράδειγμα μας το 392):

ALTER DATABASE db_test SET SINGLE_USER WITH ROLLBACK IMMEDIATE
GO
DBCC WRITEPAGE(db_test, 1, 392, 0, 1, 0x41, 1)
DBCC WRITEPAGE(db_test, 1, 392, 1, 1, 0x41, 1)
DBCC WRITEPAGE(db_test, 1, 392, 2, 1, 0x41, 1)
GO
ALTER DATABASE db_test SET MULTI_USER
GO
Αφού προκαλέσαμε το corruption ας περάσουμε στον πίνακα και άλλη εγγραφή

Σαν να μην έφτανε το corruption που προκαλέσαμε ας περάσουμε και άλλη μία εγγραφή μετά το corruption που δεν θέλουμε να την χάσουμε:

INSERT INTO db_test.dbo.pinakas (onoma,tilefono,epitheto) VALUES ('Agamemnonas','693333333',null)
GO

*Παραρήρησα ότι σε αντίθεση με τις παλαιότερες εκδόσεις στον SQL Server 2019 δεν σε αφήνει να περάσεις καινουργια εγγραφή αν έχεις corruption στον πίνακα. Αυτό σίγουρα κάνει πιο εύκολη την διαδικασία της ανάκτησης αλλά καθώς μπορεί να έχουμε παλαιότερη έκδοση θεωρούμε για την ανάγκη του άρθρου ότι υπάρχει η εγγραφή περασμένη μετά το corruption.

Τι θα συμβεί αν προσπαθήσουμε τώρα να δούμε τον πίνακα
select * from db_test..pinakas
Πώς κάνουμε restore συγκεκριμένο μόνο page στον SQL Server

Μας λέει ξεκάθαρα ότι κάτι δεν πάει καλά και δεν μπορούμε να προσπελάσουμε τον πίνακα.

Πως βρίσκουμε που ακριβώς έχει συμβεί το corruption

Για αρχή τρέχοντας checkdb θα δούμε ότι το πρόβλημα βρίσκεται στον συγκεκριμένο πίνακα:

dbcc checkdb (db_test)
Πώς κάνουμε restore συγκεκριμένο μόνο page στον SQL Server

μέσα από το view της msdb βλέπουμε ποιο page έχει γίνει corrupt:

select * from msdb.dbo.suspect_pages
Πώς κάνουμε restore συγκεκριμένο μόνο page στον SQL Server
Πως θα δούμε τι backups έχουμε πάρει τη βάση για να δούμε τι θα κάνουμε
SELECT [media_set_id]
   ,[media_count]
   ,[physical_device_name]
   ,[device_type]
   ,[physical_block_size]
 FROM [msdb].[dbo].[backupmediafamily]
Πώς κάνουμε restore συγκεκριμένο μόνο page στον SQL Server

Επαναφέροντας το corrupted page

Για αρχή θα πρέπει να πάρουμε ένα transaction log backup που θα περιέχει την πληροφορία από ότι έχει γίνει στη βάση από το τελευταίο backup:

BACKUP LOG db_test TO
	DISK = 'C:\backups\db_test_logb.bak'
	WITH INIT
GO

Έπειτα εκτελούμε το κλασικό restore database με την παράμετρο όμως του page ώστε να γίνει restore μόνο το συγκεκριμένο. Κατά όλη τη διαδικασία δεν κάνουμε recovery την βάση, οπότε βάζουμε τη παράμετρο with norecovery ώστε να μην μπορούν να προστεθούν καινούργια δεδομένα στη βάση:

RESTORE DATABASE db_test
	PAGE = '1:392'
	FROM DISK= N'C:\backups\db_test_full.bak'
	WITH NORECOVERY
GO

Τώρα που η βάση έχει γίνει restore with norecovery δεν είναι προσπελάσιμη, αυτό σημαίνει ότι δεν γίνεται να περαστεί κάτι καινούργιο στη βάση. Οπότε για να είμαστε 100% σίγουροι ότι δεν θα χάσουμε πληροφορία καλούμε ένα tail log backup δηλαδή ένα transaction log backup ενώ η βάση δεν είναι recovered (προσπελάσιμη):

BACKUP LOG db_test TO
	DISK = 'C:\backups\db_test_LOG_TAIL.bak'
	WITH NORECOVERY,INIT
GO

Επαναφέρουμε το τελευταίο transaction log που πήραμε:

** Φυσικά αν από την στιγμή πού έγινε το τελευταίο full / differential backup είχανε παρθεί και άλλα transaction log backups πρέπει να γίνουν restore αυτά πρώτα με χρονολογική σειρά.

RESTORE LOG db_test FROM
	DISK = 'C:\backups\db_test_logb.bak'
	WITH NORECOVERY
GO

Τελευταίο γίνεται restore το tail log backup που πήραμε:

RESTORE LOG db_test FROM
	DISK = 'C:\backups\db_test_LOG_TAIL.bak'
	WITH NORECOVERY
GO

Αφού τελειώσαμε με τα restore καλούμε το command με recovery ώστε να ξαναγίνει προσπελάσιμη η βάση:

RESTORE DATABASE db_test WITH RECOVERY
GO

Το αποτέλεσμα

Πλέον άμα προσπαθήσουμε να κάνουμε select τον πίνακα θα φαίνονται οι εγγραφές που υπήρχανε συν αυτή που περάστηκε μετά το corruption:

select * from db_test..pinakas
Πώς κάνουμε restore συγκεκριμένο μόνο page στον SQL Server

Πηγές:

Μοιράσου το

Αφήστε μία απάντηση