/* This query grabs relevant information about active long-running snapshot transactions. This can help identify what is preventing cleanup of tempdb version store records. This can also help identify what is preventing long truncation in an Availability Group topology. */ DECLARE @old_transaction_cutoff_minutes INT = 60; SELECT SYSDATETIME() AS [runtime] , [s].[last_request_start_time] AS [last_batch] , COALESCE([tst].[open_transaction_count], [r].[open_transaction_count]) AS [open_transaction_count] , [tat].[transaction_id] , [tasdt].[transaction_sequence_num] , [tasdt].[commit_sequence_num] , [s].[session_id] AS [session_id] , [tasdt].[is_snapshot] , [tasdt].[first_snapshot_sequence_num] , [tasdt].[max_version_chain_traversed] , [tasdt].[average_version_chain_traversed] , [tasdt].[elapsed_time_seconds] , NULL AS [kpid] , CASE [r].[blocking_session_id] WHEN 0 THEN NULL WHEN NULL THEN NULL ELSE [r].[blocking_session_id] END AS [blocking_session_id] , [r].[wait_time] , [r].[last_wait_type] , [s].[database_id] AS [session_database_id] , [tdt].[database_id] AS [transaction_database_id] , [s].[cpu_time] + COALESCE([r].[cpu_time], 0) AS [cpu_time] , [s].[reads] + COALESCE([r].[reads], 0) AS [reads] , [s].[writes] + COALESCE([r].[writes], 0) AS [writes] , [s].[logical_reads] + COALESCE([r].[logical_reads], 0) AS [logical_reads] , [s].[memory_usage] + COALESCE([r].[granted_query_memory], 0) AS [memory_usage] , [c].[connect_time] , [s].[status] , [c].[client_net_address] , [s].[program_name] , [r].[command] , [s].[login_name] , [r].[request_id] , COALESCE([tdt].[total_reserved_bytes], 0) AS [log_reserved_bytes] , [tat].[name] AS [transaction_name] , CASE [tst].[open_transaction_count] WHEN NULL THEN 0 ELSE 1 END AS [is_explicit_transaction] FROM [sys].[dm_tran_active_transactions] [tat] INNER JOIN ( SELECT [tdt].[transaction_id] , [tdt].[database_id] , SUM([tdt].[database_transaction_log_bytes_reserved] + [tdt].[database_transaction_log_bytes_reserved_system]) AS [total_reserved_bytes] FROM [sys].[dm_tran_database_transactions] [tdt] WHERE [tdt].[database_id] NOT IN (1, 2, 3, 4) --Ignore the built-in databases GROUP BY [tdt].[transaction_id], [tdt].[database_id] ) [tdt] ON [tdt].[transaction_id] = [tat].[transaction_id] LEFT JOIN [sys].[dm_tran_session_transactions] [tst] --Empty for implicit transactions ON [tst].[transaction_id] = [tat].[transaction_id] LEFT JOIN [sys].[dm_tran_active_snapshot_database_transactions] [tasdt] ON [tasdt].[transaction_id] = [tat].[transaction_id] INNER JOIN [sys].[dm_exec_sessions] [s] ON [s].[session_id] = COALESCE([tst].[session_id], [tasdt].[session_id]) INNER JOIN [sys].[dm_exec_connections] [c] ON [c].[session_id] = [s].[session_id] LEFT JOIN [sys].[dm_exec_requests] [r] --Empty for idle sessions ON [r].[transaction_id] = [tat].[transaction_id] WHERE [tat].[transaction_begin_time] < DATEADD(MINUTE, 0 - @old_transaction_cutoff_minutes, SYSDATETIME())