Skip to content

The tempdb space alert renders "% used" while measuring reserved space, and the setting's own doc already says reserved #3144

Closed

Description

@erikdarlingdata

Reported on Discussion #3128 by @Javeeditpro, as a request for "used space instead of reserved space." The request surfaces a real defect that is narrower and more fixable than the ask: the alert is mislabelled, and the metric is correct.

The mismatch, in three places that disagree

PerformanceMonitor.Alerting/TempDbSpaceInfo.cs:

public double UsedPercent => CapacityMb > 0
    ? TotalReservedMb / CapacityMb * 100
    : 0;

The numerator is TotalReservedMb. PerformanceMonitor.Collectors/TempDbStatsCollector.cs:137 defines it:

total_reserved_mb = CONVERT(decimal(18,2), SUM(dsu.user_object_reserved_page_count + dsu.internal_object_reserved_page_count + dsu.version_store_reserved_page_count) * 8 / 1024.0),

Three reserved page counts out of tempdb.sys.dm_db_file_space_usage. So:

surface says
TempDbSpaceInfo.UsedPercent used
AlertEngine alert body and ShortMessage — $"tempdb {tempDb.UsedPercent:F0}% used" used
IAlertEngineSettings.cs:144 — "Fire when tempdb reserved space is at/above this % of total" reserved

The one surface that is already correct is the one an operator never reads. The two an operator does read are wrong.

Why the metric stays and the label changes

Reserved is the better numerator for an alert whose job is "tempdb is about to run out." Reserved pages are committed to an allocation unit and cannot be handed to anything else, so they are consumed capacity whether or not they currently hold rows. A sort or hash spill reserves substantially more than it fills and reserves it first, so a reserved-based alert fires while there is still time to act. Switching the basis to used would make the alert fire later, which is the wrong direction for an exhaustion alarm.

And a true used figure is not cheaply available. sys.dm_db_file_space_usage exposes the reserved page counts, unallocated_extent_page_count and the extent totals — there is no used-pages column. The nearest source is sys.dm_db_partition_stats.used_page_count inside tempdb, which covers user objects only: internal objects (sorts, hashes, spools) and the version store do not appear there, and on a busy server those are frequently the bulk of consumption. A "used" number would therefore be both more expensive to collect and incomplete in exactly the cases where it matters most.

Scope

Rename and re-word so every surface states what is measured. The property, the alert body, the ShortMessage, and any viewer/docs text that renders it.

Two things NOT in scope, deliberately:

  • Do not change the numerator. The reasoning above is the whole point of the issue.
  • Do not touch CapacityMb. It is the growth ceiling (SUM(max_size) over tempdb's ROWS files) rather than the current allocation, and that is The tempdb Space alert's percentage has no size floor, and on Azure SQL Database that makes it fire on one temp table #2515's fix, not a bug: dividing by the allocation measured distance to the next autogrow, and on Azure SQL Database one ordinary ~57 MB #temp table read 95.7% full against the allocation and 0.09% against the real cap. MaxSizeMb's three states (positive = real cap, -1 = unlimited growth, 0 = snapshot predates the column) are load-bearing and documented; leave them.

Watch for

UsedPercent is a public member of a shared assembly read by both SKUs. Find every consumer before renaming — Darling alerting, the web viewer, the WPF viewer, and Lite — because a partial rename leaves two names for one number, which is worse than one wrong name.

The threshold setting is TempDbSpaceThresholdPercent and its doc is already correct. Do not "fix" it into agreement with the wrong text.

Acceptance

  1. No operator-facing string describes this number as "used" while it is computed from reserved page counts.
  2. A pin that fails if the rendered alert text and the numerator's provenance disagree — i.e. one that reds if someone renames the property back, or swaps the numerator without touching the label. A pin asserting only that a particular word is present does not satisfy this; it must be sensitive to the mismatch itself.
  3. The #2515 denominator reasoning survives in CapacityMb's doc comment, unedited.
  4. Default threshold behaviour is unchanged — this is a labelling change and must not move when anything fires.

Queue

Queued for after the pending nightly cut and install. Not to be dispatched before then.

Activity

  1. erikdarlingdata commented on Sep 7, 2026

    @erikdarlingdata
    OwnerAuthor

    Claude posting for Erik Darling

    Closed by #3148, merged to dev at 467cc24a6a6b826c5c134d56e499082162e5c49e. Closing by hand — closing keywords do not fire here, since merges land on dev while the default branch is main.

    The label is now what changed; the metric is unchanged, as scoped. Acceptance criterion 2 is met by an instrument that can actually fail: the basis is derived per run rather than asserted — a fixture whose members each take a distinct whole-number share of the denominator goes through the real AlertContextBuilders.BuildTempDbSpaceContext, the percentage is read back out of the rendered heading, and the member whose share equals it is the numerator. No member name appears in the derivation, which is what lets the member's own name be judged as a label rather than becoming a compile error. The numerator-swap mutation reds by naming the mismatch.

    Two things worth recording from the work. The identifier census was not sufficient — a fourth sweep on the rendered label strings found four more files that assert the text and never name the member, which a rename-only pass would have left red. And two of the eleven mutations found defects in the pin rather than the code, including a strip-rather-than-replace case that did not red because a per-file rule was satisfied while both strings an operator is actually paged with had lost the word. Reading the assertions would not have surfaced that.

    Still open and deliberately out of scope: two #2349 doc comments (AlertEngine.cs:1297, DatabaseFileGrowthInfo.cs:15) describe the pre-#2515 denominator, and the claim built on them — that the percentage falls as tempdb balloons, which is the stated justification for the file-growth alert existing — no longer holds for a capped tempdb. That is a denominator claim, which this issue excluded, and it is not operator-facing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions