Last DBCC CheckDB Known Good

Overview

DBCC CHECKDB is the only thing that proves a database is readable. This report shows when each database was last proved readable, and how far that has drifted.

Every database is drawn as a dot on a shared time axis anchored at Today. A working maintenance window shows up as a vertical column of dots at roughly the same date. The databases the job is not covering are exactly the ones that have drifted out of that column – which is a thing you can see at a glance and cannot see in a list of timestamps.

The dot area is the database’s size, so a large unchecked database is visually larger than a small one. The second view weighs the same answer by allocated size outright, because a list of nine rows cannot tell you that two of them hold three quarters of the data.

The axis is logarithmic in time. A database checked yesterday and one checked last year both have to fit on the same chart, and a linear axis would squash the recent half-inch into nothing.


Where to find it

Route How
Server tree Right-click the server → Instance Level ReportsLast DBCC CheckDB Known Good by Database
Server Overview page Click the report link
Related Links bar From Backup Status, Suspect Pages and QuickScan
Report arrows Sits between Sessions and Deadlock History in the instance report order
The Last DBCC CheckDB Known Good report
The whole report. A working maintenance window is a vertical column of dots; anything right of it has drifted out.

The page title reads Last DBCC CheckDB Known Good by Database for <server name>. The help button opens https://databasehealth.com/server-overview/instance-level-reports/dbcc-last-known-good/.

The chart is also captured into the SQL Server Health Report advisor output.


Requirements

The last known good date comes from one of two places, and which one decides what permissions you need.

SQL Server version Source Needs
2016 SP2 and later DATABASEPROPERTYEX(name, 'LastGoodCheckDbTime') Ordinary access to sys.databases
Earlier than 2016 SP2 DBCC DBINFO walked per database The sysadmin role

The subtitle line tells you which one was used on every load: read from DATABASEPROPERTYEX or read from DBCC DBINFO.

If you are on an older instance without sysadmin, nothing can be read and the notice band says so plainly:

This instance is older than SQL Server 2016 SP2, so the last known good date has to come from DBCC DBINFO – which needs the sysadmin role. Nothing could be read with the permissions this connection has.

The query timeout is 120 seconds, because the DBCC DBINFO fallback walks every database and that takes a while on a large instance.

The report is driven from sys.databases outward, so a database that could not be read is drawn as unknown rather than silently vanishing from the page.

tempdb and database snapshots are excluded. Neither can be checked in the way this report means, and listing them as “Never” forever is noise dressed as a finding.


Setting your thresholds

Three values on the Thresholds tab of the Settings dialog decide the bands.

Setting Meaning Default
CheckDBShowGreen Checked within this many days is Fresh 2
CheckDBShowYellow Up to this many days is Current 30
CheckDBShowRed Up to this many days is Watch; beyond it is Overdue 60

They are read defensively rather than trusted – each is forced greater than the one before it, because the dialog stores whatever was typed and a set that runs backwards would draw the zones inside out.

The three thresholds are contiguous by construction, and that is the defect this replaces. The old page coloured under two days green and over thirty amber and left everything between them uncoloured, so a database checked on Sunday and one checked four weeks ago looked identical.

The bands

Band Age Meaning
Fresh within the fresh threshold Checked in the last maintenance window.
Current up to the yellow threshold Older than fresh, still inside the interval the instance is meant to keep.
Watch up to the red threshold Past the interval, not yet at the point of alarm.
Overdue beyond the red threshold The rows this report exists to find.
Never checked No DBCC CHECKDB has ever reported this database consistent.
Unknown Could not be read – offline, restoring, or no permission. Drawn hollow.

Chips

A short chip sits beside each database name, naming the finding rather than making you read the colour:

Chip When
Overdue (red) Past the red threshold.
Watch (amber) Past the yellow threshold.
Never checked (red) Never checked, and the database is older than the yellow threshold.
New 12 days ago (outlined) Never checked, but created within the yellow threshold. A database created last week has not missed anything yet, so it is stated as context rather than accused.
Unknown (outlined) Could not be read.

Fresh and Current rows get no chip. Running your eye down the chip gutter is the problem list.


The two views

Timeline (the default)

One row per database, with a dot placed on a shared logarithmic time axis anchored at Today. Dot area is the database size.

The freshness timeline, one dot per database on a shared time axis
Dots cluster into a column where the maintenance window is working. Dot area is the database size, so a large unchecked database is visually larger.

The legend hint reads dot area is database size · click a row to find it in the grid · right-click for scripts.

Coverage

The same answer weighed by allocated size rather than by row count – a single stacked bar, one segment per band, widths proportional to bytes.

Clicking a segment filters the whole page to that band; clicking it again clears the filter. The hint reads segment width is allocated size · click a segment to show only those databases.

This is the view that answers “how much of my data is actually verified”, which is a different question from “how many of my databases are”.


The header lines

The summary line, for example:

14 databases carry 2.1 TB · 3 have never been checked · 61% of it verified in the last 30 days

The middle clause escalates: never-checked databases are named first if any exist, otherwise the overdue count and the oldest one, otherwise just the oldest check. The percentage is measured in bytes.

The subtitle line states the axis, the thresholds and the source:

ranked by how long ago · log time axis, so a database checked yesterday and one checked last year both fit · thresholds 2 / 30 / 60 days from Settings · read from DATABASEPROPERTYEX · tempdb and database snapshots are not checked

The amber notice band appears when something needs saying:

  • The pre-2016-SP2 permission message above.
  • N databases could not be read – offline, restoring, or not visible to this login. They are drawn hollow rather than left off the page.
  • N databases have pages already recorded in msdb.dbo.suspect_pages. A recent known good date does not clear those – open the Suspect Pages report.

That last one matters. A green Fresh row and known corruption are not mutually exclusive, and the report says so rather than letting the colour reassure you.


Chart interactions

Gesture Result
Hover a row Full tooltip
Left-click a row Selects the matching grid row
Left-click a coverage segment Filters the page to that band; click again to clear
Double-click a row Opens the DBCC CheckDB dialog for that database
Right-click a row The database menu, plus Copy Chart to Clipboard
Right-click empty space Copy Chart to Clipboard only

The tooltip:

Sales
2026-06-14 02:11 · 52 days ago

Size 412 GB
State ONLINE
Recovery FULL
Page verify CHECKSUM

Ages are written the way a person would say them – today, 1 day, 47 days, 8 months, 1y 8m, 3 years – rather than as a raw day count. “624 days” is arithmetic nobody asked for.


Reading the grid

The grid, with age bars and coloured Status
Age and Size draw in-cell bars. Status is printed in the band colour.
Column Units What it is
Database Database name.
Last Known Good date When DBCC CHECKDB last reported it consistent, or Never, or Unknown.
Age days / months / years How long ago that was. Drawn with an in-cell bar.
Size bytes Allocated size. Drawn with an in-cell bar.
Page Verify CHECKSUM, TORN_PAGE_DETECTION, NONE, or -.
Recovery SIMPLE, FULL or BULK_LOGGED.
State ONLINE, RESTORING, OFFLINE and so on.
Status The band name, printed in the band colour.

Sorting

  • Age sorts on a raw number. Never-checked rows sort as a very large number and unreadable rows sort as -1past the end, not before the start, so sorting by age puts your worst databases at the top rather than burying them behind rows nobody could read.
  • Last Known Good is written as MMM d yyyy h:mm tt on purpose. That is the shape the grid’s comparer recognises as a date. An ISO date would read better and sort worse, because the comparer would take the leading 2026 for a number and call every date in the year equal. (The old page could not sort this column at all – its cell text began with a [RED]: colour tag, so the sort was by colour and then by month name as a word.)

The toolbar

Group Buttons
View Timeline · Coverage
Filter All · Watch · Overdue · Never checked · Unreadable
Refresh

A filter button with no rows behind it disables itself, so the toolbar tells you whether you have any overdue databases before you click anything. Filtering to Fresh or Current, which have no button, is done by clicking their segment in the Coverage view; the toolbar then shows a label such as showing fresh only.

There is no auto-refresh and no countdown, deliberately. A last known good date changes when a CHECKDB job finishes, which is a weekly event on most instances. A countdown on this page would be decoration.


Right-click actions

This report is unusual in that two of its menu items actually do something. The rest copy scripts to the clipboard and run nothing.

Item What it does
Run DBCC CheckDB (action) Opens the DBCC CheckDB dialog for that database, which runs the check and shows its progress.
Set PAGE_VERIFY to CHECKSUM (action) Shown only when page verify is not already CHECKSUM. Confirms first, then runs ALTER DATABASE ... SET PAGE_VERIFY CHECKSUM.
Copy Database Name to Clipboard Just the name.
Copy DBCC CheckDB Script to Clipboard A full check.
Copy PHYSICAL_ONLY Script to Clipboard The faster check for large databases and tight windows.
Copy Snapshot CheckDB Script to Clipboard Checks against a database snapshot, so the check does not hold the live database.
Copy PAGE_VERIFY CHECKSUM Script to Clipboard The ALTER DATABASE statement rather than running it.
Copy Suspect Pages Query to Clipboard Shown when the database already has rows in msdb.dbo.suspect_pages.
Copy Weekly CheckDB Job Script to Clipboard A whole-instance weekly job, ready for SQL Agent. Not row-specific.

About Set PAGE_VERIFY to CHECKSUM

The confirmation says what the change does and does not do, because this is widely misunderstood:

Page verify is NONE on this database, so a torn or mis-written page is not noticed when SQL Server reads it back.

Only pages written after this change carry a checksum. The pages already on disk stay unverified until something rewrites them, so run a full DBCC CheckDB afterwards.

If the database is read-only it adds that nothing is being written to it, so the setting will not start protecting anything until that changes.

The statement runs on its own connection with a 120 second timeout – setting a database option is instant, but the statement waits behind whatever else holds the database.


How to read the report

  1. Look for the column. A healthy instance draws a vertical column of dots at roughly the same date. That is the maintenance window working.
  2. Look for what has drifted right of it. Those are the databases the job is not covering – usually ones added after the job was written.
  3. Read the notice band. Unreadable databases and existing suspect pages both change what the colours mean.
  4. Check the dot sizes. A large dot far from the column is worth more of your attention than a small one.
  5. Switch to Coverage. Row counts and byte counts tell different stories, and Coverage is the one that answers “how much of my data is verified”.
  6. Check the Page Verify column. A database with page verify NONE is one where corruption is not noticed when SQL Server reads a page back – a recent CHECKDB is worth less there.
  7. Right-click the worst row and either run the check or copy the script into your maintenance job.

Common patterns

One database far right of the column, everything else tight. It is not in the job. Check the job definition for a hard-coded database list.

Everything drifting right together. The job stopped running. Go to Job History.

A Fresh row with a suspect pages notice. Corruption was already recorded. A clean CHECKDB since then does not remove those rows from msdb.dbo.suspect_pages – open Suspect Pages and deal with them explicitly.

A row reading Never that was restored recently. Restoring a database does not carry the source’s last known good date. It genuinely has not been checked here, and that is worth knowing.

Several rows reading Unknown. Offline, restoring, or not visible to this login. They are drawn hollow rather than dropped, so they cannot be mistaken for healthy.

Page verify not CHECKSUM on an old database. Common on databases upgraded from SQL Server 2000, where TORN_PAGE_DETECTION was the default. The right-click menu will set it, with the caveat that only future writes are protected.


Where the data comes from

One query per load against the monitored instance. Nothing is stored.

  • sys.databases – the list, plus state, recovery model, read-only flag and page verify setting.
  • DATABASEPROPERTYEX(..., 'LastGoodCheckDbTime') on SQL Server 2016 SP2 and later.
  • DBCC DBINFO per database on earlier versions, which needs sysadmin.
  • sys.master_files – allocated size.
  • msdb.dbo.suspect_pages – the count behind the suspect pages notice.

The modern path asks DATABASEPROPERTYEX rather than the old sp_MSforeachdb plus DBCC DBINFO combination, which is both faster and does not need elevated rights.


Settings

Setting Default Values Set by
CheckDbFreshnessView timeline timeline, coverage The view buttons
CheckDBShowGreen 2 days Settings dialog, Thresholds tab
CheckDBShowYellow 30 days, must exceed green Settings dialog, Thresholds tab
CheckDBShowRed 60 days, must exceed yellow Settings dialog, Thresholds tab

Messages you may see

Nothing readable:

No databases could be read on this instance. This needs to see sys.databases, and the last known good date comes from DATABASEPROPERTYEX – or, before SQL Server 2016 SP2, from DBCC DBINFO, which needs the sysadmin role.

Timed out:

The last known good lookup did not finish in time. On an instance older than SQL Server 2016 SP2 this walks every database with DBCC DBINFO, which takes a while when there are a great many; try Refresh.


Report Why you would go there
Suspect Pages Corruption already recorded. A known good date does not clear it.
Backup Status A backup of a corrupt database is a corrupt backup. These two belong together.
Job History Why the CHECKDB job stopped running.
Databases by Size Which databases are large enough to need PHYSICAL_ONLY or a snapshot check.

Frequently asked questions

Why is tempdb not listed? It cannot meaningfully be checked and is rebuilt at every startup. On the old page it read “Never” forever.

Why does a database say Never when I know it has been checked? Either the check ran before a restore (the date does not travel with a restored database), or the check reported errors – the date only advances on a check that found the database consistent.

Why is the time axis logarithmic? So a database checked yesterday and one checked last year both fit on one chart. On a linear axis every recent check would collapse into a single point at the right-hand edge.

What is the difference between the two views? Timeline counts databases. Coverage counts bytes. Three tiny unchecked databases and one 4 TB unchecked database are very different problems, and only Coverage shows that.

Does a green row mean the database is definitely healthy? It means it was consistent when last checked. If the notice band mentions suspect pages, or Page Verify is not CHECKSUM, treat that green with less confidence.

Does Set PAGE_VERIFY to CHECKSUM fix existing corruption? No. It does not repair anything and does not verify anything already on disk. Only pages written after the change carry a checksum. The confirmation dialog says exactly this.

Why does this report not refresh itself? A last known good date changes when a weekly job finishes. Use Refresh.