如何找出哪些进程导致数据库或数据库文件自动增长?

Mar*_*lli 3 process sql-server tempdb sql-server-2014

我有一个进程渴望 tempdb,但我正在努力识别这个进程。

\n\n

我有什么方法可以实现这一目标?

\n\n
\n

我们已收到警报,因为 Tempdb 现在已占据您之前在 T:\\ 驱动器上回收的空间。同样,磁盘上还剩余 10MB。从今天早上 10:18 开始,我可以在 REP 实例上的数据文件中看到许多自动增长事件。总共有 330 个自动增长事件,每个事件大小为 512MB,总计 168GB。

\n\n

事后很难强调什么在 Tempdb 中使用了这个空间,您是否知道今天有任何进程可能以这种方式使用 Tempdb?

\n
\n\n

/ ------------------------------------------------- ----------- \\

\n\n

确定自动增长事件发生的频率

\n\n

当 SQL Server 执行自动增长事件时,触发自动增长事件的事务必须等到自动增长事件完成后才能完成。当自动增长事件发生时,这些自动增长事件会导致您的性能略有下降。因此,最好能够适当调整数据库大小,以便很少发生自动增长事件。

\n\n

如果您对系统上自动增长事件发生的频率感兴趣,您可以使用跟踪捕获这些事件。通过了解哪些数据库正在执行自动增长事件,您可以调整这些数据库文件增长属性,以便它们执行自动增长事件的频率降低。您可以使用探查器 \xe2\x80\x9cData File Auto-grow\xe2\x80\x9d 和/或 \xe2\x80\x9cLog File Auto-grow\xe2\x80\x9d 事件来跟踪这些数据库自动增长事件。如果您运行的是 SQL Server 2005 或更高版本,则默认跟踪已捕获这两个自动增长事件。如果您还没有\xe2\x80\x99t 关闭默认跟踪,那么您可以使用默认跟踪文件来查找这些自动增长事件。如果您已关闭默认跟踪,则可以启用它,或者设置新的探查器跟踪以捕获 \xe2\x80\x9cData File Auto-grow\xe2\x80\x9d 和 \xe2\x80\x9cLog File Auto-grow \xe2\x80\x9d 事件。

\n\n

默认跟踪记录到文件中。我在清单 4 中提供了代码,向您展示如何从默认跟踪文件中提取所有自动增长事件。如果您创建自己的探查器跟踪会话来捕获这些自动增长事件,那么您将需要修改此脚本以满足您的探查器跟踪设置。

\n\n

https://www.simple-talk.com/sql/database-administration/sql-server-database-growth-and-autogrowth-settings/

\n\n

马塞洛·米奥雷利\n2014 年 3 月 11 日

\n\n
\\*--------------------------------------------------*/\nDECLARE @filename NVARCHAR(1000);\nDECLARE @bc INT;\nDECLARE @ec INT;\nDECLARE @bfn VARCHAR(1000);\nDECLARE @efn VARCHAR(10);\n\n-- Get the name of the current default trace\nSELECT @filename = CAST(value AS NVARCHAR(1000))\nFROM ::fn_trace_getinfo(DEFAULT)\nWHERE traceid = 1 AND property = 2;\n\n-- rip apart file name into pieces\nSET @filename = REVERSE(@filename);\nSET @bc = CHARINDEX(\'.\',@filename);\nSET @ec = CHARINDEX(\'_\',@filename)+1;\nSET @efn = REVERSE(SUBSTRING(@filename,1,@bc));\nSET @bfn = REVERSE(SUBSTRING(@filename,@ec,LEN(@filename)));\n\n-- set filename without rollover number\nSET @filename = @bfn + @efn\n\n-- process all trace files\nSELECT \n  ftg.StartTime\n,te.name AS EventName\n,DB_NAME(ftg.databaseid) AS DatabaseName  \n,ftg.Filename\n,(ftg.IntegerData*8)/1024.0 AS GrowthMB \n,(ftg.duration/1000)AS DurMS\nFROM ::fn_trace_gettable(@filename, DEFAULT) AS ftg \nINNER JOIN sys.trace_events AS te ON ftg.EventClass = te.trace_event_id  \nWHERE (ftg.EventClass = 92  -- Date File Auto-grow\n    OR ftg.EventClass = 93) -- Log File Auto-grow\nORDER BY ftg.StartTime\n
Run Code Online (Sandbox Code Playgroud)\n

Kin*_*hah 5

找出导致自动增长的进程​​的唯一方法是使用扩展事件。EVENT--> sqlserver.database_file_size_change&sqlserver.databases_log_file_size_changedACTION--> sqlserver.sql_text

看起来@DBA_ANDY 已经完成了编写 XEvent 的艰苦工作

-- Original Author : @DBA_ANDY http://nebraskasql.blogspot.com/2016/06/finding-file-growths-with-extended.html
-- Modified by : Kin to filter on tempdb autogrowth events
SET NOCOUNT ON 
/* Create Extended Events Session */
IF EXISTS (SELECT 1 FROM master.sys.server_event_sessions WHERE name = 'DemoFileSize')
 DROP EVENT SESSION [DemoFileSize] ON SERVER
GO
CREATE EVENT SESSION [DemoFileSize] ON SERVER
ADD EVENT sqlserver.database_file_size_change(SET collect_database_name=(1)
    ACTION(package0.collect_system_time,sqlos.task_time,
 sqlserver.client_app_name,sqlserver.client_hostname,
 sqlserver.client_pid,sqlserver.database_id,sqlserver.database_name,
 sqlserver.server_instance_name,sqlserver.session_id,
 sqlserver.sql_text,sqlserver.username)
 WHERE ( [database_id] = ( 2 ) -- This is tempdb database id
),
 /* Note -  predicate/filter - will collect only for tempdb */
ADD EVENT sqlserver.databases_log_file_size_changed(
    ACTION(package0.collect_system_time,sqlos.task_time,
 sqlserver.client_app_name,sqlserver.client_hostname,
 sqlserver.client_pid,sqlserver.database_id,sqlserver.database_name,
 sqlserver.server_instance_name,sqlserver.session_id,
 sqlserver.sql_text,sqlserver.username)
 WHERE ( [database_id] = ( 2 ) -- This is tempdb database id
  )
 /* Note -  predicate/filter - will collect only for tempdb */
ADD TARGET package0.event_file(SET filename=N'D:\XEvent_logs\DemoFileSize.xel',-- change HERE !!
 max_file_size=(500),max_rollover_files=(10))
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,
 MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,
 MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=OFF,STARTUP_STATE=ON)
GO

ALTER EVENT SESSION [DemoFileSize] ON SERVER
STATE = START;
GO
Run Code Online (Sandbox Code Playgroud)

粉碎 XEvent xml ...

SELECT
Case when file_type = 'Data file' Then 'Data File Grow' Else File_Type End AS [Event Name]
, database_name AS DatabaseName
, dateadd(minute, datediff(minute, sysutcdatetime(), sysdatetime()), timestamp1) as LocalTimeStamp
/* added the timestamp and in XE is UTC - this code converts it to local server time zone */
, file_names
, size_change_mb
, duration
, client_app_name AS Client_Application
, client_hostname
, session_id AS SessionID
, sql_txt   ----------------> This is the process TSQL text !
, sql_username
, Is_Automatic

FROM
(
SELECT
(n.value ('(data[@name="size_change_kb"]/value)[1]', 'int')/1024.0) AS size_change_mb
, n.value('(@timestamp)[1]', 'datetime2') as timestamp1
, n.value ('(data[@name="database_name"]/value)[1]', 'nvarchar(50)') AS database_name
, n.value ('(data[@name="duration"]/value)[1]', 'int') AS duration
, n.value ('(data[@name="file_type"]/text)[1]','nvarchar(50)') AS file_type
, n.value ('(action[@name="client_app_name"]/value)[1]','nvarchar(50)') AS client_app_name
, n.value ('(action[@name="session_id"]/value)[1]','nvarchar(50)') AS session_id
, n.value ('(action[@name="client_hostname"]/value)[1]','nvarchar(50)') AS Client_HostName
, n.value ('(data[@name="file_name"]/value)[1]','nvarchar(50)') AS file_names
, n.value ('(data[@name="is_automatic"]/value)[1]','nvarchar(50)') AS Is_Automatic
, n.value ('(action[@name="sql_text"]/value)[1]','nvarchar(500)') AS sql_txt
, n.value ('(action[@name="username"]/value)[1]','nvarchar(50)') AS sql_username

FROM
(
SELECT CAST(event_data AS XML) AS event_data
FROM sys.fn_xe_file_target_read_file(
N'D:\XEvent_logs\DemoFileSize*.xel' -- CHANGE HERE !!
, NULL
, NULL
, NULL
)
) AS Event_Data_Table
CROSS APPLY event_data.nodes('event') AS q(n)) xyz
ORDER BY timestamp1 desc
Run Code Online (Sandbox Code Playgroud)

下面是输出:

在此输入图像描述 重要的事 :