Skip to content

v3.5.1 - Failed stats CommandLog logging fix (gh-515)

Choose a tag to compare

@nanoDBA nanoDBA released this 07 May 18:47
· 58 commits to main since this release

Bug fix: failed UPDATE STATISTICS rows now traceable in CommandLog

Reported by: @nanoDBA in #515

What was broken

When sp_StatUpdate hit an error during UPDATE STATISTICS, the per-stat CATCH branch did write a CommandLog row (via the existing two-phase pre-exec INSERT + post-exec UPDATE pattern), but the failure UPDATE only set EndTime / ErrorNumber / ErrorMessage -- it left ExtendedInfo NULL.

Consequences:

  • Failure rows had no RunLabel (RunLabel is denormalized into ExtendedInfo XML, not a column)
  • Filtering CommandLog by run label + ErrorNumber <> 0 returned zero rows
  • sp_StatUpdate_Diag's C2 (REPEATED_FAILURES) check extracts RunLabel from XML and silently missed every failure -- post-incident debugging was impossible from CommandLog alone, only the aggregate StatsFailed count survived

What changed

The real-failure ELSE branch in the per-stat CATCH (@stats_failed += 1 path) now builds the same ExtendedInfo XML schema as the success path -- including RunLabel, ObjectId, StatsId, ModificationCounter, RowCount, PageCount, all QS metrics, QualifyReason, Mode, EffectiveSamplePct, SampleSource, Version, etc. -- and the failure UPDATE now sets ExtendedInfo.

Wrapped in TRY/CATCH so a XML build error falls back to NULL ExtendedInfo without breaking the failure UPDATE.

TOCTOU rows (errors 208, 15009, 2767 -- object/stat dropped between discovery and exec) intentionally keep NULL ExtendedInfo so they don't aggregate as real failures in diag C2. These are tracked separately via @stats_toctou per the existing #222 design.

Verification

  • End-to-end: synthesized 4 failure rows mirroring the post-fix CATCH XML schema, ran sp_StatUpdate_Diag -- C2 surfaces Statistic fails consistently: gh515_synth.dbo.BigFact.IX_BigFact_col1 -- Failed in 4 run(s). Errors: 1222
  • Test suites on SQL 2022 CU24: V3Core 16/16, V3Extended 16/16, V3Fixes 10/10, V3Coverage 11/11 (including new T80 regression test verifying RunLabel round-trips through ExtendedInfo XML and diag's GROUP BY/HAVING contract finds the failures)
  • Note: SQL 2019 / SQL 2025 containers were not reachable on the test host at release time; XML construction uses standard FOR XML PATH which is identical across SQL 2017+ and the change is non-version-gated

Commit

92e9e21 -- v3.5.1: failed stats now write CommandLog ExtendedInfo with RunLabel (gh-515)