powershelldba.de · Uwe Janke

DBCC CHECKDB: Detecting and Surviving Corruption

What CHECKDB actually checks, why REPAIR_ALLOW_DATA_LOSS is a last resort and not a first move, and the backup-first workflow that turns a corruption incident into a non-event.

Corruption is the incident every DBA hopes never actually happens and plans for anyway. Disks fail silently, firmware bugs write bad pages, storage arrays lie about durability guarantees they don't actually keep. DBCC CHECKDB is how you find out before a query does, and how it's run in the minutes after discovery determines whether the incident costs you an hour or costs you data permanently.

What CHECKDB Actually Checks

Running DBCC CHECKDB('MyDatabase') isn't one check, it's several, bundled together:

If PAGE_VERIFY isn't set to CHECKSUM, you're flying without the instrument that detects most corruption. Check it now: SELECT name, page_verify_option_desc FROM sys.databases;. Older databases migrated forward for years sometimes still carry NONE or the older TORN_PAGE_DETECTION from a setting nobody revisited.

The Workflow, in Order

  1. Run CHECKDB and read the actual output, not just the exit status. A clean run returns no errors; any error means stop and think before touching anything else.
  2. Check whether you have a good backup. If MyDatabase has a recent, verified full backup and enough log backups to bring it current, restoring is almost always faster and safer than repairing in place, this is why SQL Server Backup Concepts and this article are really one topic split in two: the backup strategy you built before the incident is what determines your options during it.
  3. If restoring, restore to a different location first and verify the restored copy is actually clean with its own CHECKDB run, before cutting over, don't overwrite your only remaining known-bad copy until the replacement is confirmed good.
  4. If you must repair in place, start with the least destructive option, REPAIR_REBUILD (fixes issues that don't risk data loss, like nonclustered index corruption which can simply be rebuilt from the clustered index/heap) before ever considering REPAIR_ALLOW_DATA_LOSS.
  5. Only reach for REPAIR_ALLOW_DATA_LOSS when there is no usable backup and the alternative is losing the whole database. It works by deleting whatever's corrupted to bring the database back to a structurally consistent state, consistent, not complete. Know exactly what that means before running it: data is gone, not fixed.
-- Diagnose only, no changes made
DBCC CHECKDB('MyDatabase') WITH NO_INFOMSGS, ALL_ERRORMSGS;

-- Least destructive repair, safe to attempt (still needs single-user mode)
ALTER DATABASE MyDatabase SET SINGLE_USER WITH ROLLBACK IMMEDIATE;
DBCC CHECKDB('MyDatabase', REPAIR_REBUILD);
ALTER DATABASE MyDatabase SET MULTI_USER;

-- Last resort only, after confirming no viable backup exists
DBCC CHECKDB('MyDatabase', REPAIR_ALLOW_DATA_LOSS);
Repair option What it does Data loss risk
No repair, just diagnose Reports errors, changes nothing None, this should always be the first run
REPAIR_REBUILD Fixes issues recoverable without discarding data (e.g. rebuilding a corrupted nonclustered index from intact source data) None for the issues it can actually fix; refuses to touch issues it can't
REPAIR_ALLOW_DATA_LOSS Deletes corrupted pages/rows to restore structural consistency Real and permanent; whatever was on those pages is gone

Prevention Beats Repair

Common Gotchas

The Bottom Line

CHECKDB's job is to tell you the truth about your database's structural integrity, and the moment it reports an error is not the moment to start improvising. Restore from a verified backup when you have one, that's almost always faster and safer than any in-place repair. When you don't, work from the least destructive option upward, and treat REPAIR_ALLOW_DATA_LOSS as exactly what its name says: a last resort, not a first move.