Quick Scan Report – Dangerous Versions of SQL Server
What this check looks for
The build revision from SERVERPROPERTY('ProductVersion'), against the ranges Microsoft has identified as carrying a corruption bug:
| Major version | Affected build revisions |
|---|---|
| SQL Server 2012, major version 11 | 2100 to 3436, and 5058 to 5521 |
| SQL Server 2014, major version 12 | 2000 to 2369 |
ProductVersion reads as major.minor.build.revision, and the number being tested is the build, the third part. On 11.0.5058.0 that is 5058, which falls in the second 2012 range.
Why it matters
This is not a configuration you chose or a practice you can change. It is a defect in the engine, and while you are on one of these builds, ordinary correct maintenance can corrupt your data.
The best known of these is the online index rebuild bug, which affected parallel online index rebuild operations and could silently corrupt an index. What makes it serious is the shape of it:
- It is caused by the maintenance you are told to do. Rebuilding indexes online, in parallel, on a large table is the recommended practice on Enterprise edition. The instances most likely to hit it are the well maintained ones.
- It is silent. There is no error at the time. The corruption is discovered later by
DBCC CHECKDB, or by a query returning wrong results, and by then it is in the backups too. - Every backup taken since is suspect. Which means the window in which you hold a clean backup is closing on your retention schedule, exactly as with any other corruption.
This is filed as Critical rather than as a version finding because of that last point. Being on an old version is a risk you can schedule around. Being on one of these builds is a risk that compounds every night your backup retention rolls over.
How to confirm it yourself
SELECT SERVERPROPERTY('ProductVersion') AS [version],
SERVERPROPERTY('ProductLevel') AS [service_pack],
SERVERPROPERTY('ProductUpdateLevel') AS [cumulative_update],
SERVERPROPERTY('Edition') AS [edition],
PARSENAME(CONVERT(VARCHAR(32), SERVERPROPERTY('ProductVersion')), 4) AS [major],
PARSENAME(CONVERT(VARCHAR(32), SERVERPROPERTY('ProductVersion')), 2) AS [build];
Compare the build against the table above.
Then find out whether it has already happened, which is the question that matters more than the version number:
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 when each database was last verified clean:
DBCC DBINFO ('YourDatabase') WITH TABLERESULTS; -- read dbi_dbccLastKnownGood
How to fix it
Patch, and stop doing the thing that triggers it until you have.
- Apply the latest service pack and cumulative update for your version. Both of these were fixed years ago, so any current build is out of the affected range. This is the whole fix, and it needs a restart and therefore a window.
- Until you have patched, stop online index rebuilds, or run them with
MAXDOP = 1, which avoids the parallel path the bug lives in:
ALTER INDEX [YourIndex] ON [dbo].[YourTable]
REBUILD WITH (ONLINE = ON, MAXDOP = 1);
Offline rebuilds and reorganizes are not affected. If your maintenance window can take an offline rebuild, that is the safer choice in the meantime. 3. Run DBCC CHECKDB across every database before and after patching, so you know whether you are patching ahead of the problem or cleaning up after it:
DBCC CHECKDB ('YourDatabase') WITH NO_INFOMSGS, ALL_ERRORMSGS;
- If CHECKDB finds anything, follow the corruption check rather than this one. Restore from a backup taken before the damage; do not reach for a repair option first.
While you are planning the patch, consider the larger question. SQL Server 2012 left extended support in July 2022 and 2014 in July 2024, so an instance on one of these builds is also unsupported. Patching to the last available update removes this specific risk and leaves the support one, which the end of life check covers.
How long it takes
About four hours for the patch itself, plus a maintenance window. Running CHECKDB across every database beforehand takes as long as your databases are large, and it is the part not to skip.
Related reports
| Report | Why you would go there |
|---|---|
| Suspect Pages | Whether corruption has already been recorded. |
| Last DBCC CheckDB Known Good by Database | When each database was last verified clean. |
| Migration Planner | The bigger move, since these versions are also out of support. |
| Server Overview | Version, edition and build in one place. |
| Backup Status | Which backups exist, given that recent ones may carry the damage. |
| Index Fragmentation | The maintenance that triggers the bug. |
Related checks
| Check | |
|---|---|
| DBCC CHECKDB Corruption Errors Found | What to do if it has already happened. |
| SQL Server Version is past support end of life | The support side of the same version. |
| Version updates available | A supported version missing its latest update. |
| Reindexing during the day | The maintenance to pause until you have patched. |
| DBCC CheckDB never run | Whether anything would have caught this. |
Frequently asked questions
We have never seen corruption. Is this urgent? The bug is silent, so not having seen it and not having it are different statements. Running DBCC CHECKDB is how you turn one into the other.
We do not use online index rebuilds. Then you are much less exposed, and patching is still the answer because the exposure is not something you want to depend on nobody changing.
What build should we be on? The last cumulative update released for your version. For 2012 and 2014, both are out of support, so there will be no more, and the last one is the end of the line.
Does this affect SQL Server 2016 and later? Not these particular ranges. Other builds have had other issues, which is the argument for staying current rather than for any one version.