问题表现:
tempdb的数据文件暴增,无法收缩。
查看tempdb用在哪里?
监视tempdb磁盘空间:
如何确定 tempdb 中的可用空间量,以及如何确定版本存储区、内部对象和用户对象使用的空间量。
确定 tempdb 中的可用空间量
下面的查询将返回 tempdb 中所有文件的总可用页数和总可用空间量 (MB)。
SELECT SUM(unallocated_extent_page_count) AS [free pages],
(SUM(unallocated_extent_page_count)*1.0/128) AS [free space in MB]
FROM sys.dm_db_file_space_usage;
确定版本存储区使用的空间量
下面的查询将返回 tempdb 中版本存储区使用的总页数和总空间量 (MB)。
SELECT SUM(version_store_reserved_page_count) AS [version store pages used],
(SUM(version_store_reserved_page_count)*1.0/128) AS [version store space in MB]
FROM sys.dm_db_file_space_usage;
确定运行时间最长的事务
如果版本存储区使用了 tempdb 中的大量空间,则必须确定运行时间最长的事务。使用下面的查询可按顺序(事务的最长运行时间)列出活动事务。
SELECT transaction_id,session_id
FROM sys.dm_tran_active_snapshot_database_transactions
ORDER BY elapsed_time_seconds DESC;
与联机索引操作无关的长时间运行的事务需要很大的版本存储区。此版本存储区保存自事务启动以来生成的所有版本。联机索引生成事务可能需要较长时间才能完成,但是使用了专用于联机索引操作的单独的版本存储区。因此,这些操作不会防止删除其他事务的版本。有关详细信息,请参阅行版本控制资源的使用情况。
确定内部对象使用的空间量
下面的查询将返回 tempdb 中内部对象使用的总页数和总空间量 (MB)。
SELECT SUM(internal_object_reserved_page_count) AS [internal object pages used],
(SUM(internal_object_reserved_page_count)*1.0/128) AS [internal object space in MB]
FROM sys.dm_db_file_space_usage;
确定用户对象使用的空间量
下面的查询将返回 tempdb 中用户对象使用的总页数和总空间量。
SELECT SUM(user_object_reserved_page_count) AS [user object pages used],
(SUM(user_object_reserved_page_count)*1.0/128) AS [user object space in MB]
FROM sys.dm_db_file_space_usage;
确定总空间量(可用空间和已用空间)
下面的查询将返回 tempdb 中所有文件使用的磁盘空间总量。
SELECT SUM(size)*1.0/128 AS [size in MB]
FROM tempdb.sys.database_files
SQL:
select
sm.sysno sosysno
,sm.orderdate
,replace(replace(replace(replace((ar.ProvinceName + ar.CityName + ar.DistrictName + sm.ReceiveAddress),char(10),''),char(13),''),char(9),''),',','') address
,ar.CityName city
from master sm
left join Area as ar
on ar.SysNo = sm.ReceiveAreaSysNo
where 1=1
and convert(varchar(10),sm.orderdate,111) between convert(varchar(10),getdate()-1,111) and convert(varchar(10),getdate()-1,111)
and sm.ordertype <>5
and replace(replace(replace(replace((ar.ProvinceName + ar.CityName + ar.DistrictName + sm.ReceiveAddress),char(10),''),char(13),''),char(9),''),',','') is not null
确定问题是行版本控制导致了tempdb的占用。事务持有未释放长达522696秒。
抓到那句SQL。杀掉会话。tempdb空间释放。
SELECT transaction_id,session_id
FROM sys.dm_tran_active_snapshot_database_transactions
ORDER BY elapsed_time_seconds DESC;
可以进行tempdb的空间收缩了。
PS:查询当前数据库tempdb在 用户对象和 内部对象的使用量:
SELECT top 10 t1.session_id,
t1.internal_objects_alloc_page_count, t1.user_objects_alloc_page_count,
t1.internal_objects_dealloc_page_count , t1.user_objects_dealloc_page_count,
t3.login_name,t3.status,t3.total_elapsed_time
from sys.dm_db_session_space_usage t1
inner join sys.dm_exec_sessions as t3
on t1.session_id = t3.session_id
where (t1.internal_objects_alloc_page_count>0
or t1.user_objects_alloc_page_count >0
or t1.internal_objects_dealloc_page_count>0
or t1.user_objects_dealloc_page_count>0)
order by t1.internal_objects_alloc_page_count desc
internal_objects_alloc_page_count:内部对象使用量
user_objects_alloc_page_count:用户对象使用量
internal_objects_dealloc_page_count:内部对象释放量
user_objects_dealloc_page_count:用户对象释放量