【问题标题】:Check if stored procedure is running检查存储过程是否正在运行
【发布时间】:2014-09-15 10:47:14
【问题描述】:

如何检查存储过程或查询是否仍在 SQL Server 中运行?

想法

  1. 我曾想过在程序开始时在哪里写入日志,并在程序结束时将其删除。

    缺陷:

    • 当服务器重新启动或过程内部出现某种故障时,它会保持开放状态。
    • 此方法在运行程序前需要做一些工作,因此不能应用于已经运行的程序。
  2. 使用进程监视器

我更喜欢一种可以作为存储过程并入的解决方案,其中procedure_name 和/或pidparameters 作为输入,因此使用 SQL Server 接口跟踪程序或解决方案将不起作用。


更新 #1


使用示例:

CREATE PROCEDURE dbo.sp_sleeping_beauty 
    @time_str varchar(50)
AS 
   SET NOCOUNT ON;
   WAITFOR DELAY @time_str;
GO

dbo.sp_sleeping_beauty '00:00:10'
dbo.sp_sleeping_beauty '00:00:20'
dbo.sp_sleeping_beauty '00:00:30'

过程应该像这样调用

test_if_running 'dbo.sp_sleeping_beauty '00:00:20''

并在运行时(20 秒)返回 true,如果函数失败或系统重新启动,则返回 false

【问题讨论】:

  • 一个真实的例子是,当更多的用户或过程使用一个不能同时使用的存储过程时,必须检查该过程是否已经在运行

标签: sql sql-server stored-procedures


【解决方案1】:

更新: John Clayton 给出的答案引用了outdated SQL Server 2000 system table (sys.sysprocesses)。更新后的 SQL 是:

SELECT
  object_name(st.objectid) as ProcName
FROM
  sys.dm_exec_connections as qs 
CROSS APPLY sys.dm_exec_sql_text(qs.most_recent_sql_handle) st 
WHERE
  object_name(st.objectid) is not null

上面的 SQL 代码返回您正在运行的进程的名称列表。请注意,您将need permission to view the Server/Database state

【讨论】:

  • 看来这个查询返回运行进程的名称服务器范围,而不仅仅是在它运行的数据库上。这可能是也可能不是预期的行为,具体取决于用例,但最好注意这一点。
【解决方案2】:

您可以查询 sys.dm_exec_requests,它将提供会话 ID、等待时间和更多感兴趣的行,并 CROSS APPLY sys.dm_exec_sql_text 使用您的过程的 SQL 过滤您的查询。

Select * from
(
SELECT * FROM sys.dm_exec_requests 
where sql_handle is not null
) a 
CROSS APPLY  sys.dm_exec_sql_text(a.sql_handle) t 
where t.text like 'CREATE PROCEDURE dbo.sp_sleeping_beauty%'

【讨论】:

  • 有效,但我很好奇为什么 sql_text CREATE PROCEDURE ..
  • 如果您只过滤%dbo.sp_sleeping_beauty%,您也会发现上面显示的您自己的查询,因为它包含dbo.sp_sleeping_beauty,您可能会找到另一种方法来避免这种情况。例如where t.text like '%dbo.sp_sleeping_beauty%' and a.session_ID<>@@SPID
  • 明白,但我会在开始程序之前进行测试,所以没关系,我只是好奇 t.text 列代表什么
【解决方案3】:

使用这个:

exec sp_who2 

它返回所有数据库活动。

您将从这个过程中检查您的程序是否正在运行。

也会尝试:

 SELECT  creation_time , object_name(st.objectid) as ProcName
        ,last_execution_time
        ,total_physical_reads
        ,total_logical_reads 
        ,total_logical_writes
        , execution_count
        , total_worker_time
        , total_elapsed_time
        , total_elapsed_time / execution_count avg_elapsed_time
        ,SUBSTRING(st.text, (qs.statement_start_offset/2) + 1,
         ((CASE statement_end_offset
          WHEN -1 THEN DATALENGTH(st.text)
          ELSE qs.statement_end_offset END
            - qs.statement_start_offset)/2) + 1) AS statement_text
FROM sys.dm_exec_query_stats AS qs
CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st
ORDER BY total_elapsed_time / execution_count DESC;

【讨论】:

  • 不错,但它不显示过程名称,只显示它当前正在执行的命令,你能根据sp_sleeping_beauty的例子举个例子吗?
  • 第二种解决方案不显示过程名称,似乎只适用于查询
  • 现在检查第二列给你过程名称
  • dbo.sp_sleeping_beauty '00:00:20',用过object_name(st.objectid) LIKE '%sp_sleeping_beauty%' 并且不行...
【解决方案4】:

旧线程,但你可以这样做,

SELECT @object = object_id
FROM SYS.OBJECTS
WHERE NAME = [SP NAME]

Select *
from        (
SELECT *
FROM sys.dm_exec_requests
where sql_handle is not null
)                                              a
CROSS APPLY sys.dm_exec_sql_text(a.sql_handle) t
where objectid = @object

【讨论】:

    【解决方案5】:

    我一直在试图弄清楚如何获取正在运行的程序列表并遇到了这个线程。在对MSDN 进行一些研究后,我能够找出以下查询,它将提供正在运行的进程列表:

    select 
      object_name(st.objectid) as ProcName 
    from 
      sys.sysprocesses as qs 
      CROSS APPLY sys.dm_exec_sql_text(qs.sql_handle) st 
    where 
      object_name(st.objectid) is not null
    

    需要更多的工作来获取参数。

    【讨论】:

      猜你喜欢
      • 2020-11-21
      • 2018-12-19
      • 1970-01-01
      • 1970-01-01
      • 2011-08-08
      • 2012-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多