查找哪个会话持有哪个临时表


14

我们有一个SQL Server 2005数据库,临时数据库已满。通过进入SQL Server Management Studio,我可以看到tempdb中的所有临时表。是否可以判断哪个会话正在保存哪个临时表?理想情况下,该查询将列出每个会话使用的临时表。

谢谢,


1
我们想追踪使用临时数据库中空间的特定用户。它是当前的任务tempdb的消费,我们感兴趣的
SQLMIKE

Answers:


16

我要求在2007年在Connect上内置一些功能。这在2008年版本中被拒绝,随后被忽略,直到几年前Connect死亡。我试图在SQL Server的新反馈站点上找到它,但该搜索绝对是垃圾场。我的请求的标题是“将映射表映射到session_id的dmv”-由于搜索只能做OR,因此“映射表映射”返回118页的结果。谷歌似乎建议他们杀死Connect时并没有削减成本

同时,对于SQL Server 2005和2008,您应该能够从默认跟踪中提取此信息:

DECLARE @FileName VARCHAR(MAX)  

SELECT @FileName = SUBSTRING(path, 0,
   LEN(path)-CHARINDEX('\', REVERSE(path))+1) + '\Log.trc'  
FROM sys.traces   
WHERE is_default = 1;  

SELECT   
     o.name,   
     o.OBJECT_ID,  
     o.create_date, 
     gt.NTUserName,  
     gt.HostName,  
     gt.SPID,  
     gt.DatabaseName,  
     gt.TEXTData 
FROM sys.fn_trace_gettable( @FileName, DEFAULT ) AS gt  
JOIN tempdb.sys.objects AS o   
     ON gt.ObjectID = o.OBJECT_ID  
WHERE gt.DatabaseID = 2 
  AND gt.EventClass = 46 -- (Object:Created Event from sys.trace_events)  
  AND o.create_date >= DATEADD(ms, -100, gt.StartTime)   
  AND o.create_date <= DATEADD(ms, 100, gt.StartTime)

乔纳森·凯海耶斯(Jonathan Kehayias)的这篇博客文章毫不客气地将其解除

要确定空间使用情况,您可以进一步增强它以从诸如sys.db_db_partition_stats-的视图中加入数据:

DECLARE @FileName VARCHAR(MAX)  

SELECT @FileName = SUBSTRING(path, 0,
   LEN(path)-CHARINDEX('\', REVERSE(path))+1) + '\Log.trc'  
FROM sys.traces   
WHERE is_default = 1;  

SELECT   
     o.name,   
     o.OBJECT_ID,  
     o.create_date, 
     gt.NTUserName,  
     gt.HostName,  
     gt.SPID,  
     gt.DatabaseName,  
     gt.TEXTData,
     row_count = x.rc,
     used_page_count = x.upc
FROM sys.fn_trace_gettable( @FileName, DEFAULT ) AS gt  
JOIN tempdb.sys.objects AS o   
     ON gt.ObjectID = o.OBJECT_ID
INNER JOIN
(
 SELECT [object_id], SUM(row_count), SUM(used_page_count)
   FROM tempdb.sys.dm_db_partition_stats
   WHERE index_id IN (0,1)
   GROUP BY [object_id]
) AS x(id, rc, upc)
ON x.id = o.[object_id]
WHERE gt.DatabaseID = 2 
  AND gt.EventClass = 46 -- (Object:Created Event from sys.trace_events)  
  AND o.create_date >= DATEADD(ms, -100, gt.StartTime)   
  AND o.create_date <= DATEADD(ms, 100, gt.StartTime)

这里的问题是试图通过查询文本来关联表名。这只是不切实际,因为在大多数情况下,用户仍未对该表执行查询(没关系,仍在运行创建/填充该表的查询)。

但是,这是供其他读者(或升级时的读者)使用,如果#temp表是堆,则2012+中的默认跟踪将不再跟踪临时表对象的创建。不知道这是巧合还是与从2012年开始所有临时表现object_id都为负的事实直接相关。您当然可以移至扩展事件以帮助您收集和跟踪此信息,但这可能是很多手动工作(而且我只验证了它已不再跟踪)-您可能无法选择它在扩展事件中)。默认跟踪 拾取由PK或其他约束创建的#temp表,或者在创建事件之后添加约束或索引创建的#temp表,但随后您必须放宽上述基于时间的约束(索引创建时间晚于100ms,创建)。

本网站上的其他一些答案可能会有用:

我还通过自定义“扩展事件”会话在博客上进行了跟踪,以跟踪SQL Server 2012及更高版本中的此信息:

保罗·怀特(Paul White)在博客中直接阅读网页(不完全是出于胆小,也不容易以任何方式实现自动化):


5

这是一个查询,可以帮助您开始查找所需的信息:

select top 10
    tsu.session_id,
    tsu.request_id,
    r.command,
    s.login_name,
    s.host_name,
    s.program_name,
    total_objects_alloc_page_count = 
        tsu.user_objects_alloc_page_count + tsu.internal_objects_alloc_page_count,
    tsu.user_objects_alloc_page_count,
    tsu.user_objects_dealloc_page_count,
    tsu.internal_objects_alloc_page_count,
    tsu.internal_objects_dealloc_page_count,
    st.text
from sys.dm_db_task_space_usage tsu
inner join sys.dm_exec_requests r
on tsu.session_id = r.session_id
and tsu.request_id = r.request_id
inner join sys.dm_exec_sessions s
on r.session_id = s.session_id
outer apply sys.dm_exec_sql_text(r.sql_handle) st
where tsu.user_objects_alloc_page_count > 0
or tsu.internal_objects_alloc_page_count > 0
order by total_objects_alloc_page_count desc;

该查询为前10个任务提取有用的信息,例如分配/取消分配的页面,任务的SQL文本(如果有)等。

这些DMV充满了重要信息,因此,如果您需要更多数据,则可以与要提取的内容混合搭配。但这应该是对当前tempdb消耗任务进行故障诊断的起点。


谢谢,看起来不错。奇怪的是,如果我在tempdb上运行“ Top Tables的磁盘使用情况”报告,则使用最多空间的表不会出现在st.text中。运行查询后,该表仍然存在。
SQLMIKE 2014年

1
@SQLMIKE如果只想知道哪个表最大,则可以从中获取tempdb.sys.dm_db_partition_stats。不幸的是,您无法真正分辨出哪个副本#some_table_name属于哪个用户,也永远无法在任何给定时间提取引用该表的语句文本-可能不是该用户当前正在运行的查询。你可能想看看这个这个
阿龙贝特朗
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.