Quick Scan Report – DBCC CheckDB Never Run

What this check looks for

Databases whose last known good CHECKDB date is null or zero, meaning DBCC CHECKDB has never completed successfully against them on this instance. tempdb is excluded, because it is recreated at every restart.

The date comes from the database’s own boot page, where SQL Server records dbi_dbccLastKnownGood whenever a CHECKDB passes cleanly. It survives restarts and it moves with the database through a restore, so it is a property of the database rather than of the server.

Why it matters

Corruption is not rare, it is silent, and this is the only thing that looks for it.

Everything else that would tell you is either after the fact or by chance:

  • A query returns wrong results, and nobody notices because nobody knew what the right answer was.
  • A user hits an error reading one row out of millions.
  • A restore fails, which is the worst possible moment to find out.

DBCC CHECKDB is the only mechanism that goes looking. On a database where it has never run, corruption could have been present for years, and every backup you hold contains it.

The danger is specifically about your backups. Retention is the clock. If corruption occurred eight weeks ago and you keep four weeks of backups, the last clean copy has already aged out and nobody knows yet. Running CHECKDB is how you find out whether that clock is running, and its result also tells you which backups are worth keeping.

A database that has never been checked is usually one that arrived outside the normal process: restored for a project, attached from another server, created by an application installer, or added after the maintenance jobs were written. That is the same population as the databases with no backups, and often literally the same databases.

Note what this check is not. It is not “CHECKDB has not run recently”, which is a separate and less severe finding. It is “CHECKDB has never run at all”.

How to confirm it yourself

Per database, read the boot page:

DBCC DBINFO ('YourDatabase') WITH TABLERESULTS;

Find the dbi_dbccLastKnownGood row. A date of 1900-01-01 00:00:00.000 means never.

Across the instance, without a cursor:

CREATE TABLE #dbcc (ParentObject VARCHAR(255), [Object] VARCHAR(255),
                    Field VARCHAR(255), [Value] VARCHAR(255), DbName VARCHAR(255) NULL);

EXEC sp_MSforeachdb N'
    IF ''?'' NOT IN (''tempdb'')
    BEGIN
        INSERT INTO #dbcc (ParentObject, [Object], Field, [Value])
        EXEC (''DBCC DBINFO([?]) WITH TABLERESULTS, NO_INFOMSGS'');
        UPDATE #dbcc SET DbName = ''?'' WHERE DbName IS NULL;
    END';

SELECT DbName,
       [Value] AS [last_known_good],
       CASE WHEN [Value] LIKE '1900%' THEN 'NEVER' ELSE 'checked' END AS [state]
  FROM #dbcc
 WHERE Field = 'dbi_dbccLastKnownGood'
 ORDER BY [Value];

DROP TABLE #dbcc;

The Last DBCC CheckDB Known Good report in this product answers the same question without the scaffolding.

How to fix it

Run it now, then schedule it. Both halves matter: running it once tells you where you stand today, scheduling it is what keeps the answer current.

DBCC CHECKDB ('YourDatabase') WITH NO_INFOMSGS, ALL_ERRORMSGS;

NO_INFOMSGS suppresses the per-object noise so anything printed is a problem. ALL_ERRORMSGS stops it truncating the list at 200.

On a large or busy database, be aware of the cost before you start. CHECKDB is I/O heavy and it uses tempdb substantially. Options:

  • Run it in a maintenance window.
  • Use WITH PHYSICAL_ONLY, which is much faster and catches most real corruption, as a nightly check with a full check weekly.
  • Run it against a restored copy on another server. This is the best answer available: it costs the production instance nothing, and it tests your backups at the same time. A clean CHECKDB on a restored copy tells you both that the data is good and that the backup works.

Then schedule it. Ola Hallengren’s DatabaseIntegrityCheck handles databases individually, continues past a failure, and can be given a time limit, all of which the built in maintenance plan task cannot.

Make sure a failure reaches somebody. A CHECKDB that finds corruption and writes it to a job history nobody reads is only marginally better than not running it. The error log check in this report covers that, and an operator on the job covers the job failing outright.

How long it takes

About an hour to schedule it properly. The first run takes as long as your databases are large, which is the reason to start it now rather than to plan it.


Report Why you would go there
Last DBCC CheckDB Known Good by Database The same question for every database, in one view.
Suspect Pages Corruption already recorded, whatever CHECKDB has or has not done.
Backup Status Which backups exist, and therefore what your deadline is.
Maintenance Window Finder When the instance is quiet enough to run it.
Large Tables What is going to dominate the runtime.
Alerts and Operators Whether a failure would reach anyone.
Check
DBCC CheckDB not run recently Checking that used to happen and has stopped.
DBCC CHECKDB Corruption Errors Found What to do when it finds something.
Default Maintenance Plan Check Integrity Task The built in task, and why a script beats it.
Page verify option Whether SQL Server would notice corruption between checks.
No recent backups Very often the same databases.

Frequently asked questions

The database is small and unimportant. Then CHECKDB costs seconds and there is no reason not to. “Unimportant” databases have a habit of turning out to matter at the worst moment.

We run CHECKDB on the production copy of this database elsewhere. Corruption is per copy, because it is caused by the storage under that copy. A clean check on one server says nothing about another.

Does a backup with CHECKSUM catch corruption? It catches corruption in pages as they are read during the backup, which is genuinely useful and is why that setting matters. It does not do the logical consistency checking CHECKDB does.

Why is the date 1900-01-01? That is the zero value SQL Server stores when no successful CHECKDB has ever been recorded. It is what this check is looking for.