From 046a0c72cb67c2e3986c1b1fe73383be77205aa9 Mon Sep 17 00:00:00 2001 From: Erik Darling <2136037+erikdarlingdata@users.noreply.github.com> Date: Thu, 11 Jun 2026 06:53:41 +0100 Subject: [PATCH] Fix SQL view/analyzer crash + Linux CPU gap from Fable code review (chunk 6) - 26 blocking_deadlock_analyzer: LEFT(deadlock_group, CHARINDEX(',',...) - 1) throws "invalid length parameter" whenever deadlock_group has no comma (it's free-text from sp_BlitzLock, format can drift), aborting the whole analyzer transaction and losing the run's blocking aggregation too. Now falls back to the whole string when there's no comma (COALESCE(NULLIF(CHARINDEX,0)-1, LEN)). - 47 daily_summary: the CPU_CRITICAL test used raw total_cpu_utilization, which is NULL on SQL Server on Linux, so daily_summary could never report CPU_CRITICAL there. Added the #1048 ISNULL(total, sqlserver) fallback that the other CPU branches already use. Validation: both scripts CREATE OR ALTER cleanly on SQL2016, exit 0. 2017-2025 need your version testing. Remaining view/FinOps findings flagged for follow-up (deeper rewrites): 46 expensive_queries_today drops multi-interval Query Store queries, SUMs cumulative DMV counters (N x inflation), and has no date filter despite "today"; 54 FinOps efficiency flags healthy idle servers UNDER_PROVISIONED (anti-savings direction); 47 top_memory_consumers SUMs a point-in-time gauge over 15 min (~3x); 46/47 query_stats_summary MAX-across-plans and query_store_regressions filter/rank mismatch; 50 TokenAndPerm threshold per NUMA node not per clerk; 12 blocking-chain view created unconditionally against a conditional base view. Co-Authored-By: Claude Opus 4.8 (1M context) --- install/26_blocking_deadlock_analyzer.sql | 2 +- install/47_create_reporting_views.sql | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/install/26_blocking_deadlock_analyzer.sql b/install/26_blocking_deadlock_analyzer.sql index 4f9e2a99..1e825606 100644 --- a/install/26_blocking_deadlock_analyzer.sql +++ b/install/26_blocking_deadlock_analyzer.sql @@ -189,7 +189,7 @@ BEGIN ( SELECT database_name = ISNULL(bl.database_name, N'UNKNOWN'), - deadlock_count = COUNT_BIG(DISTINCT LEFT(bl.deadlock_group, CHARINDEX(N',', bl.deadlock_group) - 1)), + deadlock_count = COUNT_BIG(DISTINCT LEFT(bl.deadlock_group, COALESCE(NULLIF(CHARINDEX(N',', bl.deadlock_group), 0) - 1, LEN(bl.deadlock_group)))), total_deadlock_wait_time_ms = ISNULL(SUM(bl.wait_time), 0), victim_count = SUM(CASE WHEN bl.deadlock_group LIKE N'%- VICTIM' THEN 1 ELSE 0 END) FROM collect.deadlocks AS bl diff --git a/install/47_create_reporting_views.sql b/install/47_create_reporting_views.sql index 41e5a300..80b5923d 100644 --- a/install/47_create_reporting_views.sql +++ b/install/47_create_reporting_views.sql @@ -393,7 +393,9 @@ SELECT SELECT 1/0 FROM collect.cpu_utilization_stats AS cus - WHERE cus.total_cpu_utilization >= 90 + /* total_cpu_utilization is NULL on SQL Server on Linux; fall back to the SQL-only + figure so daily_summary can still report CPU_CRITICAL there (#1048). */ + WHERE ISNULL(cus.total_cpu_utilization, cus.sqlserver_cpu_utilization) >= 90 AND cus.collection_time >= DATEADD(HOUR, -1, SYSDATETIME()) ) THEN N'CPU_CRITICAL'