Backup & Recovery from First Principles, Part 8: Verification – Your Backup Job Succeeding Proves Almost Nothing

Part 7 ended on an uncomfortable question: the “clean” full backup I used to repair a corrupted page – how did I know it was clean? This part demonstrates, with a deliberately corrupted database, exactly how little a successful backup job proves, what CHECKSUM and VERIFYONLY each actually verify, and what real verification looks like.

Illustration of a quality inspector using a scanner on a crate stamped passed, revealing hidden cracks inside, representing why backup verification needs more than RESTORE VERIFYONLY

This is part 8 of the backup and recovery series (part 1). Demo ran on SQL Server 2019 (CU32) and behaves identically on SQL Server 2025 (RTM), against a database with one page corrupted via the DBCC WRITEPAGE technique.

Exhibit A: Backing Up a Corrupt Database Succeeds

The database has a page whose checksum is wrong – any read of it throws Msg 824. Watch what a plain backup does:

Success. No warning, no error. A backup is a physical page copy: it reads pages off disk and writes them to the backup file, and by default it does not validate page checksums along the way. The corruption rode along into the backup file, faithfully preserved. Every generation of backups from now on contains it, and your retention policy is quietly aging out the last backup that predates the damage.

Exhibit B: RESTORE VERIFYONLY Blesses the Corrupt Backup

Surely the verification command catches it?

“Valid.” VERIFYONLY checks that the backup file is complete and readable: header fields, file structure, that sort of thing.[1] Critically, it can only validate page checksums if the backup was taken WITH CHECKSUM – and this one was not, so there was nothing for it to check. It answered “is this file a well-formed backup?” and everyone heard “is my data okay?”

Exhibit C: WITH CHECKSUM Catches It at Backup Time

WITH CHECKSUM makes the backup validate every page’s existing checksum as it reads it, and write a checksum over the whole backup stream.[2] The corrupt page fails validation and the backup fails loudly – which is precisely what you want. A failed backup at 2 AM is an alert; a corrupt backup discovered during a 2 AM restore is a resume-generating event. This is the difference between finding corruption on your schedule versus the disaster’s schedule.

Two prerequisites make this work:

  • The database must have page checksums to validate. PAGE_VERIFY CHECKSUM is the default for databases created on SQL Server 2005+, but databases migrated from older versions or set to NONE/TORN_PAGE_DETECTION give backup checksums little to verify at the page level. Check sys.databases.page_verify_option_desc.
  • Someone has to write WITH CHECKSUM. It is not the default for backups (backup compression’s default server setting does not enable it either). Put it in every backup command you own. The CPU cost is small; the information value is enormous. Trace flag 3023 makes it the default server-wide, if changing every job is impractical.

With a checksummed backup in hand, RESTORE VERIFYONLY ... WITH CHECKSUM finally has teeth: it re-validates every page checksum in the file without restoring it.

What Even CHECKSUM Cannot Prove

Page checksums detect what the I/O path scrambled after SQL Server last wrote the page. They do not detect logical corruption (bad index linkage, wrong metadata), memory corruption checksummed on its way to disk, or the numerous problems only DBCC CHECKDB finds. The verification ladder, each rung strictly stronger:

  1. Backup job succeeded – a file exists.
  2. WITH CHECKSUM succeeded – pages passed I/O-level validation at read time.
  3. RESTORE VERIFYONLY WITH CHECKSUM – the file is structurally sound and pages still validate.
  4. Actual test restore – the backup demonstrably restores. This is the only rung that proves the thing you actually care about.
  5. Test restore + DBCC CHECKDB – the restored database is logically consistent too. As a bonus, offloading CHECKDB to a restored copy takes the load off production.

Automate rung 5. A spare server (or spare instance – licensing for a dedicated restore-test box is cheap next to data loss) restores last night’s backups on a schedule, runs CHECKDB, and reports. Generating restore commands from msdb history does the heavy lifting; the three-layer backup strategy and why local-only backups equal no backups cover where those verified files should live. And remember from part 3: verification also means verifying the chain – all the files, not just each file.

Next: part 9 benchmarks the backup tuning knobs almost nobody touches: BUFFERCOUNT, MAXTRANSFERSIZE, BLOCKSIZE, and striping.

When did a backup last lie to you? Comments below, or find me on Bluesky or LinkedIn.

References

  1. RESTORE VERIFYONLY (Transact-SQL) – Microsoft Learn. What VERIFYONLY checks, and its dependence on backup checksums for page validation.
  2. Possible Media Errors During Backup and Restore (SQL Server) – Microsoft Learn. Backup checksums, page-checksum validation during backup, and error response options.