In this article in our stairway series on SQL Server backup and restore, we shall discuss the importance of understanding the internals of the page restoration for a database administrator. Most of the time, performing a page-level restore suffices for database availability. A good backup strategy is a key to recovery or restoration, and SQL Server provides us with an option to fix database pages at a granular level. Performing a page level restore in SQL Server is a clever option wherein the restoration of the entire VLDB database backup is not required.
Identifying the corruption and finding a solution is the key to successful restoration or recovery of the database. If the number of corrupted pages seems too large, and if the administrator feels that restoring the entire database from the most recent backup is a viable option, only in that case should the option be full restoration.
Page restore is a technique used to replace corrupted pages of information in a database with uncorrupted data from a backup. Page-level restore can be performed via SSMS or T-SQL. The intent of the restore is to fix one or more corrupted pages from the available backups. To identify corrupted pages, look for pages marked as “suspect” in the table, msdb syspect_pages.
In this series we will discuss the following topics:
- Introduction to page-level restore
- Different ways the data gets corrupted
- How to deal with corruption
- Restore a page from a full backup using SSMS and T-SQL
- And more…
Let’s explore the ways to corrupt and restore a page using a demo.
This entire illustration is based on the ProdSQLShackDemo database. Let’s walk through the following SQL to get a better understanding of the page-level restoration concepts. Here are the steps involved:
- Create the database, ProdSQLShackDemo
- Switch the database context to ProdSQLShackDemo
- Change the recovery mode of the ProdSQLShackDemo to FULL
- Create the table, SQLShackAuthor, and load some test data
- Backup the database, ProdSQLShackDemo
Let’s get straight to it….
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
CREATE DATABASE ProdSQLShackDemo; GO USE ProdSQLShackDemo; GO -- Set the recovery model of SQLShackDemo to FULL ALTER DATABASE ProdSQLShackDemo SET RECOVERY FULL; GO USE ProdSQLShackDemo; GO -- Create the table SQLShackAuthor CREATE TABLE SQLShackAuthor ( ID int IDENTITY(1,1) PRIMARY KEY, AuthorName nvarchar(100) NOT NULL ); GO --Add records to SQLShackAuthor table INSERT SQLShackAuthor VALUES ('Brain Lockwood'), ('Samir Behara'), ('Ahmad Yaseen'), ('Sifiso W. Ndlovu'), ('Marko Radakovic'), ('Bojan Petrovic'), ('Robert Seles'), ('Marko Zivkovic'), ('Luna Cvetkovic'), ('Prashanth Jayaram') ; GO USE ProdSQLShackDemo; GO SELECT * FROM SQLShackAuthor; |
1 2 3 4 5 6 |
-- Create ProdSQLShackDemo full backup to default path BACKUP DATABASE ProdSQLShackDemo TO DISK = 'f:\Program Files\Microsoft SQL Server\MSSQL14.SQL2017\MSSQL\Backup\ProdSQLShackDemo.bak' WITH FORMAT; GO |
Corruption is often very arbitrary; there are many things that can be the cause. Let’s use a tool to identify the corruption, in this demo. There are two tools that can help us with this:
- DBCC WRITEPAGE
- XVI32 by Christian Mass, a simple Hex editor freeware tool. You just need to download, extract and run the XVI32.exe
To understand the internals of how the data is organized, we can use the undocumented DBCC IND and DBCC PAGE database consistency checker commands.
DBCC IND
This Database Consistency Checker command lists all the data and index pages. The command returns the information about the actual pages that are being used in the database.
This command requires three arguments:
- Database name (ProdSQLShackDemo in our case)
- Table name (SQLShackAuthor in our case)
-
Index ID
- -1 list everything (indexes +Index Allocation Map, or IAMs)
- -2 list only IAMs
1 |
DBCC IND('ProdSQLShackDemo','SQLShackAuthor',-1) |
We can see that this only returns two pages. For the demo, I will be focusing on the page ID 153. I’m going to deliberately corrupt page 153 with two bits of information. The table SQLShackAuthor contains a value, Prashanth Jayaram, which we will meddle with, to corrupt the page in this demo.
Let’s enable the trace flag 3604 by running the following DBCC command. This option is used to redirect the output to the console.
1 2 |
DBCC TRACEON(3604) GO |
Execute the DBCC PAGE command to examine the internal page details of the data and indexes.
1 |
DBCC PAGE('ProdSQLShackDemo',1,153,3) WITH TABLERESULTS |
To turn off the trace flag
1 |
DBCC TRACEOFF (3604); |
To corrupt the page, we need to identify the starting offset of the page. Multiplying the page ID (153) with a number of bytes per page (8192) gives us the offset value.
1 |
SELECT 153*8192 AS [Offset] ---1253376 |
Make the database offline. This option enables XVI32.exe tool to edit the mdf file.
1 2 3 |
USE master; GO ALTER DATABASE ProdSQLShackDemo SET OFFLINE; |
To use XVI32
- Open XVI32.exe
- Browse to the path of the mdf file and select it
-
Go to Search or Press Ctrl+G and then type offset 1253376
-
Locate the value Prashanth on the screen and replace the character ‘s’ with ‘a’ and ‘h’ with ‘a’
-
You can see that value has been changed from ‘Prashanth’ to ‘Praaanth’. Save and close the file.
-
Bring the database online.
123USE master;GOALTER DATABASE ProdSQLShackDemo SET ONLINE; -
Run the DBCC PAGE command to view the modified value.
By default, checksums are enabled on the database. Therefore, we can see the consistency error by executing a select statement or even by running the DBCC CHECKDB command.
1 2 3 |
SELECT TOP (1000) [ID] ,[AuthorName] FROM [ProdSQLShackDemo].[dbo].[SQLShackAuthor] |
The I/O error message is shown below
The expected and actual fields in the error message clearly define the expected values and the reason for the logical inconsistency, as shown below.
Msg 824, Level 24, State 2, Line 2
SQL Server detected a logical consistency-based I/O error: incorrect checksum (expected: 0xd8b40584; actual: 0xd8b0858d).
It occurred during a read of page (1:153) in database ID 26 at offset 0x00000000132000 in file ‘f:\PowerSQL\ProdSQLShackDemo.mdf’.
Additional messages in the SQL Server error log or system event log may provide more detail.
This is a severe error condition that threatens database integrity and must be corrected immediately.
Complete a full database consistency check (DBCC CHECKDB). This error can be caused by many factors; for more information, see SQL Server Books Online.
Another way to check the results is to run the following:
1 |
DBCC CHECKDB('ProdSQLShackDemo') with tableresults |
The table results option allows an administrator to programmatically investigate the results of CHECKDB using SQL queries.
We can also query the msdb.dbo.suspect_pages table to get the details on the corrupted pages.
1 |
SELECT * from msdb.dbo.suspect_pages |
Next, let us change the recovery of the database in the database property page to NONE and then execute the select statement to view the modified data
1 |
ALTER DATABASE ProdSQLShackDemo SET PAGE_VERIFY NONE |
We can see the modified value in the following output
Performing a restore
In this section, I will take you through the steps to restore the page. Let’s revert the corrupting changes we previously made.
Before starting the restoration process, validate the consistency of every page by enabling the CHECKSUM along with PAGE_VERIFY database option. This allows the SQL Server database engine to calculate the checksum over the contents of the whole page.
1 |
ALTER DATABASE ProdSQLShackDemo SET PAGE_VERIFY CHECKSUM |
With SQL Enterprise license, one could perform a page-level restore while the database is online. The process is nothing but actually swapping the corrupt data page(s) with a copy of data pages from the backup. On other editions of the SQL Server, the recovery would be an offline process, meaning, the database has to be offline during the restore. Let’s now perform the restore.
- Browse Object-Explorer, right-click the database ProdSQLShackDemo
-
Go to tasks, select Restore and click Page….
-
In the restore page window, click the button at the top, Check Database Pages. This would identify the pages that it suspects are inconsistent, by executing the DBCC command, DBCC CHECKDB PHYSICAL_ONLY.
-
Specify the backup files to pull the data from by taking a look at the files in the backup sets section. Press the Verify button. You’ll see at the top that the backup media was verified successfully.
-
The database will go through the process of restoring the clean pages and a message on whether the process was successful or not would be displayed. we can see that the database restored successfully. Go ahead and press the OK button.
Now, let’s ensure that the data is correct by issuing the following SQL statement. You can even run the DBCC checkdb command to verify the data integrity.
1 2 3 |
SELECT TOP (1000) [ID] ,[AuthorName] FROM [ProdSQLShackDemo].[dbo].[SQLShackAuthor] |
Summary
In this article, we looked at page-level restore, by corrupting the data and then performing a recovery. The intention was to prove that restoration of data into a corrupted table is possible—simple, even—provided the backup is good.
We could take advantage of options such as checksums and torn_page_detection.
We also saw that only explicitly specified pages were restored and as such,this task would not pose any sort of resource overhead. The selected pages are replaced by the copy of the corresponding page from the specified data backup.
Table of contents
References
- More undocumented fun: DBCC IND, DBCC PAGE, and off-row columns
- Restore Pages (SQL Servers)
- Freeware Hex Editor XVI32
- Stairway to SQL essentials - April 7, 2021
- A quick overview of database audit in SQL - January 28, 2021
- How to set up Azure Data Sync between Azure SQL databases and on-premises SQL Server - January 20, 2021