我正在尝试编写一个报告当前数据库活动的查询。该查询将各种DMV链接在一起,如sys.dm_exec_connections
,sys.dm_exec_sessions
,sys.dm_exec_requests
等。该查询还会通过sys.dm_exec_sql_text
函数提取实际查询。
(我知道Activity Monitor和SQL Profiler。我需要在查询中收集这些信息,因此这些程序都不相关。)
我们系统中的大部分活动都是在存储过程和函数中进行的。在这个查询中看到这些过程的名称会很高兴。
我的问题是:
如何可靠地显示正在执行的存储过程或函数的名称?
我知道sys.dm_exec_sql_text
函数返回objectid
,我可以将此objectid
加入sys.objects
。问题是,此服务器上有多个数据库,sys.objects仅适用于当前数据库。我希望此查询能够显示正在运行的对象名称,无论该查询恰好在哪个数据库上运行。
到目前为止,我唯一的解决方案是使用sp_msforeachdb
创建一个包含所有数据库中所有对象ID和名称的临时表,并从dm_exec_sql_text
函数的结果中加入到该表中。 / p>
临时表方法有更好的解决方案吗?我觉得我错过了什么。
答案 0 :(得分:3)
我会推荐Adam Machanic的优秀sp_WhoISActive。它不会返回确切的对象名称,但会返回以可点击的形式执行的sql命令。
答案 1 :(得分:1)
- 我使用以下过程:
USE [master] GO CREATE PROC [dbo].[sp_who3] AS SET NOCOUNT ON DECLARE @LoginName varchar(128) DECLARE @AppName varchar(128) SELECT [SPID] = s.[spid] , [CPU] = s.[cpu] , [Physical_IO] = s.[physical_io] , [Blocked] = s.[blocked] , [LoginName] = CONVERT([sysname], RTRIM(s.[Loginame])) , [Database] = d.[name] , [AppName] = s.[program_name] , [HostName] = s.[hostname] , [Status] = s.[Status] , [Cmd] = s.[cmd] , [Last Batch] = s.[last_batch] , [Kill Command] = 'Kill ' + CAST(s.[spid] AS varchar(10)) , [Buffer Command] = 'DBCC InputBuffer(' + CAST(s.[spid] AS varchar(10)) + ')' FROM [master].[dbo].[sysprocesses] s WITH(NOLOCK) JOIN [master].[sys].[databases] d WITH(NOLOCK) ON s.[dbid] = d.[database_id] WHERE s.[Status] 'background' AND s.[spid] @@SPID --@CurrentSpid@ ORDER BY s.[blocked] DESC, s.[physical_io] DESC, s.[cpu] DESC, CONVERT([sysname], RTRIM(s.[Loginame])) BEGIN SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED SELECT [Spid] = er.[session_Id] , [ECID] = sp.[ECID] , [Database] = DB_NAME(sp.[dbid]) , [User] = [nt_username] , [Status] = er.[status] , [Wait] = [wait_type] , [Individual Query] = SUBSTRING(qt.[text], er.[statement_start_offset] / 2, (CASE WHEN er.[statement_end_offset] = - 1 THEN LEN(CONVERT(VARCHAR(MAX), qt.[text])) * 2 ELSE er.[statement_end_offset] END - er.[statement_start_offset]) / 2) , [Parent Query] = qt.[text] , [Program] = sp.[program_name] , [Hostname] = sp.[Hostname] , [Domain] = sp.[nt_domain] , [Start_time] = er.[Start_time] FROM [sys].[dm_exec_requests] er WITH(NOLOCK) INNER JOIN [sys].[sysprocesses] sp WITH(NOLOCK) ON er.[session_id] = sp.[spid] CROSS APPLY [sys].[dm_exec_sql_text](er.[sql_handle]) qt WHERE er.[session_Id] > 50 -- Ignore system spids. AND er.[session_Id] NOT IN (@@SPID) -- Ignore the current statement. ORDER BY er.[session_Id], sp.[ECID] END GO