for #3959 - added check for backup to NUL device#3960
for #3959 - added check for backup to NUL device#3960BrentOzar merged 3 commits intoBrentOzarULTD:devfrom
Conversation
There was a problem hiding this comment.
Pull request overview
Adds a new rule to sp_BlitzBackups (CheckId 14) to detect backups written to the Windows NUL device, highlighting both “phantom but non-chain-breaking” cases (COPY_ONLY or SIMPLE) and potentially chain-impacting cases (non-copy-only in non-SIMPLE).
Changes:
- Add CheckId 14 query to flag databases with recent backups directed to
NUL. - Split results into two findings based on
is_copy_only/recovery_modelto indicate risk level.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
| INNER JOIN ' + QUOTENAME(@MSDBName) + '.dbo.backupmediafamily bmf ON bs.media_set_id = bmf.media_set_id | ||
| WHERE UPPER(bmf.physical_device_name)= N''NUL'' | ||
| AND (bs.is_copy_only = 1 OR bs.recovery_model = N''SIMPLE'') | ||
| AND bs.backup_finish_date >= DATEADD(DAY, -30, SYSDATETIME()) |
There was a problem hiding this comment.
Instead of hard-coding 30 days back, let's use the @starttime variable, which is set via the @HoursBack input parameter on the stored proc.
| INNER JOIN ' + QUOTENAME(@MSDBName) + '.dbo.backupmediafamily bmf ON bs.media_set_id = bmf.media_set_id | ||
| WHERE UPPER(bmf.physical_device_name)= N''NUL'' | ||
| AND bs.is_copy_only = 0 AND bs.recovery_model <> N''SIMPLE'' | ||
| AND bs.backup_finish_date >= DATEADD(DAY, -30, SYSDATETIME()) |
There was a problem hiding this comment.
Instead of hard-coding 30 days back, let's use the @starttime variable, which is set via the @HoursBack input parameter on the stored proc.
| 100 AS [Priority], | ||
| bs.database_name AS [Database Name], | ||
| ''Backup to NUL device'' AS [Finding], | ||
| ''The database '' + QUOTENAME(bs.database_name) + '' has had '' + CONVERT(VARCHAR(10), COUNT(*)) + '' backups to the NUL device in the last 30 days, the latest one being on ''+ |
There was a problem hiding this comment.
Let's remove the 30 day reference and just say "backups to the NUL device, the latest one being on" since we're using the @HoursBack parameter.
| 100 AS [Priority], | ||
| bs.database_name AS [Database Name], | ||
| ''Backup to NUL device without COPY_ONLY'' AS [Finding], | ||
| ''The database '' + QUOTENAME(bs.database_name) + '' is not in SIMPLE recovery model and has had '' + CONVERT(VARCHAR(10), COUNT(*)) + '' backups to the NUL device in the last 30 days, the latest one being on ''+ |
There was a problem hiding this comment.
Let's remove the 30 day reference and just say "backups to the NUL device, the latest one being on" since we're using the @HoursBack parameter.
|
Hey @BrentOzar, Got it. Just note that I've used that date filter because I've seen it used in some of the previous checks (e.g. check IDs 7 and 12) |
Honor the @HoursBack parameter instead of a hard-coded 30-day window, matching the convention used elsewhere in this proc, and drop the "in the last 30 days" wording from the warning text now that the window is dynamic. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Thanks @VladDBA for the pull request. Merging into the dev branch, will be in the next release with credit to you in the release notes. |
The "No CHECKSUMS" (CheckId 7) and "Uncompressed backups" (CheckId 12) checks were filtering on a hard-coded 30-day window via DATEADD(DAY, -30, SYSDATETIME()) instead of the user-supplied @HoursBack window already exposed via @starttime. That ignored @HoursBack and made the warning text inconsistent with the actual window being analyzed. Replace both filters with @starttime, pass @starttime through sp_executesql, and drop the "in the last 30 days" / "in the past 30 days" wording from the findings now that the window is dynamic. Same treatment as PR BrentOzarULTD#3960 applied to CheckId 14. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Closes #3959