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 Reports → Last 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 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 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

| 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
-1– past 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 tton 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 leading2026for 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
- Look for the column. A healthy instance draws a vertical column of dots at roughly the same date. That is the maintenance window working.
- 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.
- Read the notice band. Unreadable databases and existing suspect pages both change what the colours mean.
- Check the dot sizes. A large dot far from the column is worth more of your attention than a small one.
- 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”.
- Check the Page Verify column. A database with page verify
NONEis one where corruption is not noticed when SQL Server reads a page back – a recent CHECKDB is worth less there. - 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 DBINFOper 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.
Related reports
| 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.