From 8ff0fa05b243f78bf08127de2f57c375d84c1cf2 Mon Sep 17 00:00:00 2001 From: Erik Darling <2136037+erikdarlingdata@users.noreply.github.com> Date: Sun, 1 Mar 2026 15:04:39 -0500 Subject: [PATCH] Fix SQL dumps on mirroring passive servers (RESTORING databases) OBJECT_NAME() and OBJECT_SCHEMA_NAME() with a database_id referencing a RESTORING database open the target database's metadata catalog. On mirroring passive servers, this causes severity 22 engine crashes and memory dumps. - procedure_stats: Change LEFT JOIN to INNER JOIN sys.databases with d.state = 0 filter on all 3 sub-queries (procedures, triggers, functions). Structurally excludes RESTORING database rows so OBJECT_NAME/OBJECT_SCHEMA_NAME are never evaluated for them. - query_stats: Add d.state = 0 to WHERE clause (defensive, no OBJECT_NAME calls but excludes irrelevant RESTORING database data). - file_io_stats: Replace DB_NAME(database_id) with LEFT JOIN sys.databases, use d.name instead. - waiting_tasks: Replace DB_NAME(database_id) with LEFT JOIN sys.databases, use d.name instead. Tested on sql2022: all 4 collectors run successfully with no errors. Fixes #384 Co-Authored-By: Claude Opus 4.6 --- install/08_collect_query_stats.sql | 1 + install/10_collect_procedure_stats.sql | 9 ++++++--- install/20_collect_file_io_stats.sql | 4 +++- install/37_collect_waiting_tasks.sql | 4 +++- 4 files changed, 13 insertions(+), 5 deletions(-) diff --git a/install/08_collect_query_stats.sql b/install/08_collect_query_stats.sql index 0d62c24..6ae1471 100644 --- a/install/08_collect_query_stats.sql +++ b/install/08_collect_query_stats.sql @@ -312,6 +312,7 @@ BEGIN INNER JOIN sys.databases AS d ON pa.dbid = d.database_id WHERE qs.last_execution_time >= @cutoff_time + AND d.state = 0 /*ONLINE only — skip RESTORING databases (mirroring/AG secondary)*/ AND pa.dbid NOT IN ( 1, 2, 3, 4, 32761, 32767, diff --git a/install/10_collect_procedure_stats.sql b/install/10_collect_procedure_stats.sql index 006616a..fb72c94 100644 --- a/install/10_collect_procedure_stats.sql +++ b/install/10_collect_procedure_stats.sql @@ -255,9 +255,10 @@ BEGIN FROM sys.dm_exec_plan_attributes(ps.plan_handle) AS pa WHERE pa.attribute = N'dbid' ) AS pa - LEFT JOIN sys.databases AS d + INNER JOIN sys.databases AS d ON pa.dbid = d.database_id WHERE ps.last_execution_time >= @cutoff_time + AND d.state = 0 /*ONLINE only — skip RESTORING databases (mirroring/AG secondary)*/ AND pa.dbid NOT IN ( 1, 3, 4, 32761, 32767, @@ -423,9 +424,10 @@ BEGIN FROM sys.dm_exec_plan_attributes(ts.plan_handle) AS pa WHERE pa.attribute = N'dbid' ) AS pa - LEFT JOIN sys.databases AS d + INNER JOIN sys.databases AS d ON pa.dbid = d.database_id WHERE ts.last_execution_time >= @cutoff_time + AND d.state = 0 /*ONLINE only — skip RESTORING databases (mirroring/AG secondary)*/ AND pa.dbid NOT IN ( 1, 3, 4, 32761, 32767, @@ -486,9 +488,10 @@ BEGIN FROM sys.dm_exec_plan_attributes(fs.plan_handle) AS pa WHERE pa.attribute = N'dbid' ) AS pa - LEFT JOIN sys.databases AS d + INNER JOIN sys.databases AS d ON pa.dbid = d.database_id WHERE fs.last_execution_time >= @cutoff_time + AND d.state = 0 /*ONLINE only — skip RESTORING databases (mirroring/AG secondary)*/ AND pa.dbid NOT IN ( 1, 3, 4, 32761, 32767, diff --git a/install/20_collect_file_io_stats.sql b/install/20_collect_file_io_stats.sql index 1cf5db0..d2e3f7f 100644 --- a/install/20_collect_file_io_stats.sql +++ b/install/20_collect_file_io_stats.sql @@ -133,7 +133,7 @@ BEGIN database_name = ISNULL ( - DB_NAME(vfs.database_id), + d.name, N'UNKNOWN' ), file_id = vfs.file_id, @@ -162,6 +162,8 @@ BEGIN io_stall_queued_write_ms = vfs.io_stall_queued_write_ms, sample_ms = vfs.sample_ms FROM sys.dm_io_virtual_file_stats(NULL, NULL) AS vfs + LEFT JOIN sys.databases AS d + ON d.database_id = vfs.database_id LEFT JOIN sys.master_files AS mf ON mf.database_id = vfs.database_id AND mf.file_id = vfs.file_id diff --git a/install/37_collect_waiting_tasks.sql b/install/37_collect_waiting_tasks.sql index 7d17a9d..34b0ecf 100644 --- a/install/37_collect_waiting_tasks.sql +++ b/install/37_collect_waiting_tasks.sql @@ -146,7 +146,7 @@ BEGIN blocking_session_id = ISNULL(wt.blocking_session_id, 0), resource_description = NULL, database_id = NULL, - database_name = DB_NAME(der.database_id), + database_name = d.name, query_text = NULL, statement_text = NULL, query_plan = NULL, @@ -162,6 +162,8 @@ BEGIN FROM sys.dm_os_waiting_tasks AS wt LEFT JOIN sys.dm_exec_requests AS der ON der.session_id = wt.session_id + LEFT JOIN sys.databases AS d + ON d.database_id = der.database_id OUTER APPLY sys.dm_exec_sql_text(der.sql_handle) AS dest OUTER APPLY sys.dm_exec_text_query_plan (