DBCC CHECKDB Corruption Errors Found
What this check looks for
The check reads the SQL Server error logs and looks for the messages DBCC CHECKDB writes when it finds something wrong, the ones reporting allocation errors and consistency errors. It reports the database and the message.
It is skipped when error log reading is switched off for the scan, and it reads the historic logs rather than only the current one, so a CHECKDB failure from before the last service restart is still found.
Why it matters
This is the most serious thing the Quick Scan can tell you, and it is the one finding that is worth acting on before you finish reading the report.
Corruption does not heal and it does not stay still. Every backup taken after the damage occurred contains the damage. That means the window in which you still hold a clean backup is closing on a schedule set by your backup retention, and nobody is watching that clock.
The other reason this matters more than it looks: CHECKDB found this, which means CHECKDB ran. A great many instances never run it at all, so a corruption message in the log is evidence of two things at once, that there is damage and that somebody set up the check that found it. The half of that pair which is good news does not make the other half less urgent.
Corruption is almost always a storage problem rather than a SQL Server problem. The database is the thing that noticed.
How to confirm it yourself
Run CHECKDB against the named database, and capture the output rather than watching it scroll past:
DBCC CHECKDB ('YourDatabase') WITH NO_INFOMSGS, ALL_ERRORMSGS;
Check what SQL Server has already recorded, which survives across restarts:
SELECT db.[name] AS [database_name],
sp.[file_id],
sp.[page_id],
sp.[event_type],
sp.[error_count],
sp.[last_update_date]
FROM msdb.dbo.suspect_pages AS sp WITH (NOLOCK)
LEFT JOIN sys.databases AS db WITH (NOLOCK)
ON db.[database_id] = sp.[database_id]
ORDER BY sp.[last_update_date] DESC;
And find the last time each database was known to be clean:
DBCC DBINFO ('YourDatabase') WITH TABLERESULTS;
The dbi_dbccLastKnownGood row is the timestamp of the last CHECKDB that passed.
How to fix it
Do not start by running a repair. REPAIR_ALLOW_DATA_LOSS does what its name says, and it is the last option rather than the first.
In order:
- Stop and take stock. Do not restart SQL Server, do not detach the database, and do not reboot the server. All three are instincts, and all three can turn a recoverable situation into an unrecoverable one.
- Find your last clean backup. Restore it somewhere else and run CHECKDB against the copy. Work backwards through your retention until one comes back clean. This is the step that has a deadline, because your clean backups are aging out.
- Read the CHECKDB output properly. It says which object and which pages. Damage confined to a nonclustered index is repairable by rebuilding that index and loses nothing. Damage in a clustered index or a heap is data.
- Restore, do not repair, when you can. Page level restore is available in Enterprise edition and is the least disruptive option when only a few pages are affected.
- Find the storage fault. Check the Windows system event log for disk errors, and talk to whoever owns the storage. A database that corrupted once on hardware nobody looked at will corrupt again.
If you are not confident, this is the point at which to get help. Stedman Solutions does this work: databasehealth.com.
How long it takes
Four hours is the estimate for investigating and resolving a typical case. A full restore of a large database takes as long as it takes, and finding the storage fault is a separate piece of work.
Related reports
| Report | Why you would go there |
|---|---|
| Suspect Pages | Every page SQL Server has recorded as damaged, with when and how. |
| Last DBCC CheckDB Known Good by Database | When each database was last verified clean, which sets your deadline. |
| Backup Status | Which backups exist to restore from. |
| Recovery Exposure | What restoring would cost in data and in time. |
| Error Log | The full CHECKDB output rather than the summary line. |
Related checks
| Check | |
|---|---|
| DBCC CheckDB never run | The instances where this check can never fire, which is worse. |
| DBCC CheckDB not run recently | Verification that has quietly stopped happening. |
| Page verify option | Whether SQL Server would even notice the next corruption. |
| Obsolete torn page detection | An older, weaker version of the same protection. |
Frequently asked questions
CHECKDB passes now. Was it a false alarm? Almost never. A transient hardware fault can produce a real error that a later run does not reproduce, but the page was still wrong when it was read. Treat it as a storage warning and look at the Windows event log.
The errors are in tempdb. Restart SQL Server, which rebuilds tempdb, and then investigate the storage under it. Corruption in tempdb is not a data loss event but it is the same hardware signal.
Can I just rebuild the index? If, and only if, every reported error is in a nonclustered index. The CHECKDB output names the index id. Index id 0 is a heap and index id 1 is the clustered index, and both of those are the data itself.
Why does this check read old error logs? Because the corruption message may predate the last restart, and a restart is a common reaction to a database behaving strangely. Only reading the current log would miss the message that explains the restart.