查找事务日志“tempdb”因“ACTIVE_TRANSACTION”而满的原因

use*_*567 2 sql-server sql-server-2014

我们的应用程序由于以下原因突然停止工作The transaction log for database 'tempdb' is full due to 'ACTIVE_TRANSACTION'.。现在,它又开始工作了。但我怎样才能知道这个错误出现的确切原因呢?

J.D*_*.D. 5

您可以使用此查询来获取整个服务器中正在运行的查询的列表,包括它们的进程 ID、它们运行了多长时间、它们在哪个数据库中运行、谁运行了它们、等待统计信息、阻塞查询 ID我建议将它放在存储过程中,以便您可以根据需要轻松调用它(即使使用它的默认参数),并且您可以定期使用 SQL 代理作业安排它,以将结果记录到表中。

DECLARE @Database VARCHAR(100) = NULL 
DECLARE @EntityName VARCHAR(100) = NULL
DECLARE @ExcludeMyQueries BIT = 0
DECLARE @RunningThreadsOnly BIT = 0
DECLARE @LocksOnly BIT = 0
DECLARE @MinDuration INT = 0
DECLARE @OutputMode INT = 0 -- TODO: Setup formally documented modes, and clean up usage below, can even have different kinds of modes like Verbose, vs EmergenciesOnly, etc

DECLARE @ExecutionDate DATETIME = GETDATE();

SELECT 
    SP.HostName,
    SP.SPID,    
    ER.request_id AS RequestId,
    ER.percent_complete AS PercentComplete, 
    DATEDIFF(s, start_time, @ExecutionDate) AS Duration,
    CAST(((DATEDIFF(s, start_time, @ExecutionDate)) / 3600) AS VARCHAR) + ' hour(s), '
        + CAST((DATEDIFF(s, start_time, @ExecutionDate) % 3600) / 60 AS VARCHAR) + 'min, ' 
        + CAST((DATEDIFF(s, start_time, @ExecutionDate) % 60) AS VARCHAR) + ' sec' AS RunningTime, 
    CAST((estimated_completion_time / 3600000) AS VARCHAR) + ' hour(s), ' 
        + CAST((estimated_completion_time % 3600000) / 60000 AS VARCHAR) + 'min, ' 
        + CAST((estimated_completion_time % 60000) / 1000 AS VARCHAR) + ' sec' AS EstimatedTimeRemaining, 
    DATEADD(SECOND, estimated_completion_time/1000, @ExecutionDate) AS EstimatedCompletionDate, 
    ER.Command,
    ER.blocking_session_id AS BlockingSessionId, 
    LastWaitType,  
    SP.[DBID],  
    DB_NAME(SP.[DBID]) AS DbName,       
    --[TEXT] AS EntityText,
    CPU,
    ER.plan_handle AS PlanHandle,
    ER.query_plan_hash AS QueryPlanHash,
    LOGIN_TIME AS LoginTime,
    LOGINAME AS LoginName, 
    SP.[Status],
    [PROGRAM_NAME] AS ProgramName,
    NT_DOMAIN AS NT_Domain, 
    NT_USERNAME AS NT_Username, 
    @@SERVERNAME AS ServerName,
    @ExecutionDate AS ExecutionDate 
INTO #ExecutingQueries
FROM sys.sysprocesses SP  
INNER JOIN sys.dm_exec_requests ER 
    ON sp.spid = ER.session_id 
WHERE --TEXT NOT LIKE N'%spGetRunningQueries%'
    --AND 
    DB_NAME(SP.dbid) NOT IN ('msdb','master','Distribution')    
    AND
    (
        @Database IS NULL
        OR (@Database IS NOT NULL AND @Database = DB_NAME(SP.[DBID]))
    )
    AND
    (
        @ExcludeMyQueries = 0
        OR (@ExcludeMyQueries = 1 AND hostname <> HOST_NAME())
    )   
    AND
    (
        @RunningThreadsOnly = 0
        OR (@RunningThreadsOnly = 1 AND SP.[Status] = 'RUNNABLE')
    )
    AND 
    (
        @LocksOnly = 0
        OR (@LocksOnly = 1 AND ER.blocking_session_id <> 0) -- TODO: Show the source running query that IS the blocking session ID (will need to join / union this in somehow?)
    )
    AND DATEDIFF(s, start_time, @ExecutionDate) >= @MinDuration

-- TODO: Clean this up and DON'T USE SELECT *
IF (@OutputMode = 0) -- Everything mode
BEGIN
    SELECT *
    FROM #ExecutingQueries
END
ELSE IF (@OutputMode = 1) -- Lightweight mode
BEGIN
    SELECT 
        HostName,
        SPID,
        RequestId,
        RunningTime,
        BlockingSessionId,
        LastWaitType,
        DbName,
        LEFT(EntityText, 100) AS EntityText,
        PlanHandle,
        [Status]
    FROM #ExecutingQueries
END
Run Code Online (Sandbox Code Playgroud)

使用此功能,您可以查看运行时间最长的查询(DurationRunningTime列),并通过查看LastWaitType和/或BlockingSessionId列了解它们运行这么长时间的原因。

这是我根据 Adam Machanic 的sp_WhoIsActive创建的一个正在进行的工作,我经常使用它来调试 SQL Server 上的问题。

  • 为什么不[sp_WhoIsActive](http://whoisactive.com/),它可以[轻松记录到表](https://www.brentozar.com/archive/2016/07/logging-activity-using-sp_whoisactive -采取-2/)? (4认同)