Skip to content

Commit 10192af

Browse files
authored
Merge pull request #857 from BrentOzarULTD/sp_Blitz_856
Add support for checking the default trace for weird dbcc commands
2 parents eccab41 + 5266600 commit 10192af

File tree

1 file changed

+246
-1
lines changed

1 file changed

+246
-1
lines changed

sp_Blitz.sql

Lines changed: 246 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3173,7 +3173,7 @@ AS
31733173
AND cTotal.counter_name = N'Total Server Memory (KB) '
31743174
WHERE cFree.object_name LIKE N'%Memory Manager%'
31753175
AND cFree.counter_name = N'Free Memory (KB) '
3176-
AND CAST(cTotal.cntr_value AS BIGINT) > 4000
3176+
AND CAST(cTotal.cntr_value AS BIGINT) > 20480000000
31773177
AND CAST(cTotal.cntr_value AS BIGINT) * .3 <= CAST(cFree.cntr_value AS BIGINT)
31783178
AND CAST(SERVERPROPERTY('edition') AS VARCHAR(100)) NOT LIKE '%Standard%'
31793179

@@ -3835,6 +3835,251 @@ IF @ProductVersionMajor >= 10
38353835

38363836
END;
38373837

3838+
/*Begin: checking default trace for odd DBCC activity*/
3839+
3840+
--Grab relevant event data
3841+
SELECT UPPER(
3842+
REPLACE(
3843+
SUBSTRING(CONVERT(NVARCHAR(MAX), t.TextData), 0,
3844+
ISNULL(
3845+
NULLIF(
3846+
CHARINDEX('(', CONVERT(NVARCHAR(MAX), t.TextData)),
3847+
0),
3848+
LEN(CONVERT(NVARCHAR(MAX), t.TextData)) + 1 )) --This replaces everything up to an open paren, if one exists.
3849+
, SUBSTRING(CONVERT(NVARCHAR(MAX), t.TextData),
3850+
ISNULL(
3851+
NULLIF(
3852+
CHARINDEX(' WITH ',CONVERT(NVARCHAR(MAX), t.TextData))
3853+
, 0),
3854+
LEN(CONVERT(NVARCHAR(MAX), t.TextData)) + 1),
3855+
LEN(CONVERT(NVARCHAR(MAX), t.TextData)) + 1 )
3856+
, '') --This replaces any optional WITH clause to a DBCC command, like tableresults.
3857+
) AS [dbcc_event_trunc_upper],
3858+
UPPER(
3859+
REPLACE(
3860+
CONVERT(NVARCHAR(MAX), t.TextData), SUBSTRING(CONVERT(NVARCHAR(MAX), t.TextData),
3861+
ISNULL(
3862+
NULLIF(
3863+
CHARINDEX(' WITH ',CONVERT(NVARCHAR(MAX), t.TextData))
3864+
, 0),
3865+
LEN(CONVERT(NVARCHAR(MAX), t.TextData)) + 1),
3866+
LEN(CONVERT(NVARCHAR(MAX), t.TextData)) + 1 ), '')) AS [dbcc_event_full_upper],
3867+
MIN(t.StartTime) OVER (PARTITION BY CONVERT(NVARCHAR(128), t.TextData)) AS min_start_time,
3868+
MAX(t.StartTime) OVER (PARTITION BY CONVERT(NVARCHAR(128), t.TextData)) AS max_start_time,
3869+
t.NTUserName AS [nt_user_name],
3870+
t.NTDomainName AS [nt_domain_name],
3871+
t.HostName AS [host_name],
3872+
t.ApplicationName AS [application_name],
3873+
t.LoginName [login_name],
3874+
t.DBUserName AS [db_user_name]
3875+
INTO #dbcc_events_from_trace
3876+
FROM sys.fn_trace_gettable( @base_tracefilename, DEFAULT) AS t
3877+
WHERE t.EventClass = 116
3878+
OPTION(RECOMPILE);
3879+
3880+
/*Overall count of DBCC events excluding silly stuff*/
3881+
IF NOT EXISTS ( SELECT 1
3882+
FROM #SkipChecks
3883+
WHERE DatabaseName IS NULL AND CheckID = 199 )
3884+
BEGIN
3885+
INSERT INTO [#BlitzResults]
3886+
( [CheckID] ,
3887+
[Priority] ,
3888+
[FindingsGroup] ,
3889+
[Finding] ,
3890+
[URL] ,
3891+
[Details] )
3892+
SELECT 199 AS CheckID ,
3893+
50 AS Priority ,
3894+
'DBCC Events' AS FindingsGroup ,
3895+
'Overall Events' AS Finding ,
3896+
'' AS URL ,
3897+
CAST(COUNT(*) AS NVARCHAR(100)) + ' DBCC events have taken place between ' + CONVERT(NVARCHAR(30), MIN(d.min_start_time)) + ' and ' + CONVERT(NVARCHAR(30), MAX(d.max_start_time)) +
3898+
'. This does not include CHECKDB and other usually benign DBCC events.'
3899+
AS Details
3900+
FROM #dbcc_events_from_trace d
3901+
WHERE d.[dbcc_event_trunc_upper] NOT IN (
3902+
N'DBCC CHECKCB', N' DBCC CHECKALLOC' , N'DBCC CHECKTABLE', N'DBCC CHECKCATALOG', N'DBCC CHECKFILEGROUP', --CHECKDB related
3903+
N'DBCC TRACEON', N'DBCC TRACEOFF', N'DBCC DBINFO', N'DBCC LOGINFO', N'DBCC INPUTBUFFER', N'DBCC TRACESTATUS', --Usually monitoring tool related
3904+
N'DBCC CHECKIDENT', N'DBCC SHOW_STATISTICS', N'DBCC CHECKCONSTRAINTS', --Probably rational
3905+
N'DBCC CLEANTABLE', N'DBCC CHECKPRIMARYFILE', N'DBCC OPENTRAN', 'DBCC SHOWFILESTATS' --Weird but okay
3906+
)
3907+
AND d.dbcc_event_full_upper NOT IN('DBCC SQLPERF(NETSTATS)', 'DBCC SQLPERF(LOGSPACE)')
3908+
HAVING COUNT(*) > 0
3909+
3910+
END
3911+
3912+
/*Check for someone running drop clean buffers*/
3913+
IF NOT EXISTS ( SELECT 1
3914+
FROM #SkipChecks
3915+
WHERE DatabaseName IS NULL AND CheckID = 200 )
3916+
BEGIN
3917+
INSERT INTO [#BlitzResults]
3918+
( [CheckID] ,
3919+
[Priority] ,
3920+
[FindingsGroup] ,
3921+
[Finding] ,
3922+
[URL] ,
3923+
[Details] )
3924+
SELECT 200 AS CheckID ,
3925+
50 AS Priority ,
3926+
'DBCC Events' AS FindingsGroup ,
3927+
'DBCC DROPCLEANBUFFERS' AS Finding ,
3928+
'' AS URL ,
3929+
'The user ' + COALESCE(d.nt_user_name, d.login_name) + ' has run DBCC DROPCLEANBUFFERS ' + CAST(COUNT(*) AS NVARCHAR(100)) + ' times between ' + CONVERT(NVARCHAR(30), MIN(d.min_start_time)) + ' and ' + CONVERT(NVARCHAR(30), MAX(d.max_start_time)) +
3930+
'. If this is a production box, know that you''re clearing all data out of memory when this happens. What kind of monster would do that?'
3931+
AS Details
3932+
FROM #dbcc_events_from_trace d
3933+
WHERE d.dbcc_event_full_upper = N'DBCC DROPCLEANBUFFERS'
3934+
GROUP BY COALESCE(d.nt_user_name, d.login_name)
3935+
HAVING COUNT(*) > 0
3936+
3937+
END
3938+
3939+
/*Check for someone running free proc cache*/
3940+
IF NOT EXISTS ( SELECT 1
3941+
FROM #SkipChecks
3942+
WHERE DatabaseName IS NULL AND CheckID = 201 )
3943+
BEGIN
3944+
INSERT INTO [#BlitzResults]
3945+
( [CheckID] ,
3946+
[Priority] ,
3947+
[FindingsGroup] ,
3948+
[Finding] ,
3949+
[URL] ,
3950+
[Details] )
3951+
SELECT 201 AS CheckID ,
3952+
50 AS Priority ,
3953+
'DBCC Events' AS FindingsGroup ,
3954+
'DBCC FREEPROCCACHE' AS Finding ,
3955+
'' AS URL ,
3956+
'The user ' + COALESCE(d.nt_user_name, d.login_name) + ' has run DBCC FREEPROCCACHE ' + CAST(COUNT(*) AS NVARCHAR(100)) + ' times between ' + CONVERT(NVARCHAR(30), MIN(d.min_start_time)) + ' and ' + CONVERT(NVARCHAR(30), MAX(d.max_start_time)) +
3957+
'. This has bad idea jeans written all over its butt, like most other bad idea jeans.'
3958+
AS Details
3959+
FROM #dbcc_events_from_trace d
3960+
WHERE d.dbcc_event_full_upper = N'DBCC FREEPROCCACHE'
3961+
GROUP BY COALESCE(d.nt_user_name, d.login_name)
3962+
HAVING COUNT(*) > 0
3963+
3964+
END
3965+
3966+
/*Check for someone clearing wait stats*/
3967+
IF NOT EXISTS ( SELECT 1
3968+
FROM #SkipChecks
3969+
WHERE DatabaseName IS NULL AND CheckID = 202 )
3970+
BEGIN
3971+
INSERT INTO [#BlitzResults]
3972+
( [CheckID] ,
3973+
[Priority] ,
3974+
[FindingsGroup] ,
3975+
[Finding] ,
3976+
[URL] ,
3977+
[Details] )
3978+
SELECT 202 AS CheckID ,
3979+
50 AS Priority ,
3980+
'DBCC Events' AS FindingsGroup ,
3981+
'DBCC SQLPERF(''SYS.DM_OS_WAIT_STATS'',CLEAR)' AS Finding ,
3982+
'' AS URL ,
3983+
'The user ' + COALESCE(d.nt_user_name, d.login_name) + ' has run DBCC SQLPERF(''SYS.DM_OS_WAIT_STATS'',CLEAR) ' + CAST(COUNT(*) AS NVARCHAR(100)) + ' times between ' + CONVERT(NVARCHAR(30), MIN(d.min_start_time)) + ' and ' + CONVERT(NVARCHAR(30), MAX(d.max_start_time)) +
3984+
'. Why are you clearing wait stats? What are you hiding?'
3985+
AS Details
3986+
FROM #dbcc_events_from_trace d
3987+
WHERE d.dbcc_event_full_upper = N'DBCC SQLPERF(''SYS.DM_OS_WAIT_STATS'',CLEAR)'
3988+
GROUP BY COALESCE(d.nt_user_name, d.login_name)
3989+
HAVING COUNT(*) > 0
3990+
3991+
END
3992+
3993+
/*Check for someone writing to pages. Yeah, right?*/
3994+
IF NOT EXISTS ( SELECT 1
3995+
FROM #SkipChecks
3996+
WHERE DatabaseName IS NULL AND CheckID = 203 )
3997+
BEGIN
3998+
INSERT INTO [#BlitzResults]
3999+
( [CheckID] ,
4000+
[Priority] ,
4001+
[FindingsGroup] ,
4002+
[Finding] ,
4003+
[URL] ,
4004+
[Details] )
4005+
SELECT 203 AS CheckID ,
4006+
50 AS Priority ,
4007+
'DBCC Events' AS FindingsGroup ,
4008+
'DBCC WRITEPAGE' AS Finding ,
4009+
'' AS URL ,
4010+
'The user ' + COALESCE(d.nt_user_name, d.login_name) + ' has run DBCC WRITEPAGE ' + CAST(COUNT(*) AS NVARCHAR(100)) + ' times between ' + CONVERT(NVARCHAR(30), MIN(d.min_start_time)) + ' and ' + CONVERT(NVARCHAR(30), MAX(d.max_start_time)) +
4011+
'. So, uh, are they trying to fix corruption, or cause corruption?'
4012+
AS Details
4013+
FROM #dbcc_events_from_trace d
4014+
WHERE d.dbcc_event_trunc_upper = N'DBCC WRITEPAGE'
4015+
GROUP BY COALESCE(d.nt_user_name, d.login_name)
4016+
HAVING COUNT(*) > 0
4017+
4018+
END
4019+
4020+
IF NOT EXISTS ( SELECT 1
4021+
FROM #SkipChecks
4022+
WHERE DatabaseName IS NULL AND CheckID = 204 )
4023+
BEGIN
4024+
INSERT INTO [#BlitzResults]
4025+
( [CheckID] ,
4026+
[Priority] ,
4027+
[FindingsGroup] ,
4028+
[Finding] ,
4029+
[URL] ,
4030+
[Details] )
4031+
4032+
SELECT 204 AS CheckID ,
4033+
50 AS Priority ,
4034+
'DBCC Events' AS FindingsGroup ,
4035+
'DBCC SHRINK%' AS Finding ,
4036+
'' AS URL ,
4037+
'The user ' + COALESCE(d.nt_user_name, d.login_name) + ' has run file shrinks ' + CAST(COUNT(*) AS NVARCHAR(100)) + ' times between ' + CONVERT(NVARCHAR(30), MIN(d.min_start_time)) + ' and ' + CONVERT(NVARCHAR(30), MAX(d.max_start_time)) +
4038+
'. So, uh, are they trying to fix corruption, or cause corruption?'
4039+
AS Details
4040+
FROM #dbcc_events_from_trace d
4041+
WHERE d.dbcc_event_trunc_upper LIKE N'DBCC SHRINK%'
4042+
GROUP BY COALESCE(d.nt_user_name, d.login_name)
4043+
HAVING COUNT(*) > 0
4044+
4045+
END
4046+
4047+
4048+
/*End: checking default trace for odd DBCC activity*/
4049+
4050+
/*Begin check for autoshrink events*/
4051+
4052+
IF NOT EXISTS ( SELECT 1
4053+
FROM #SkipChecks
4054+
WHERE DatabaseName IS NULL AND CheckID = 205 )
4055+
BEGIN
4056+
INSERT INTO [#BlitzResults]
4057+
( [CheckID] ,
4058+
[Priority] ,
4059+
[FindingsGroup] ,
4060+
[Finding] ,
4061+
[URL] ,
4062+
[Details] )
4063+
4064+
SELECT 205 AS CheckID ,
4065+
50 AS Priority ,
4066+
'Autoshrink events' AS FindingsGroup ,
4067+
'File shrinking' AS Finding ,
4068+
'' AS URL ,
4069+
N'The database ' + QUOTENAME(t.DatabaseName) + N' has had '
4070+
+ CONVERT(NVARCHAR(10), COUNT(*))
4071+
+ N' auto shrink events between '
4072+
+ CONVERT(NVARCHAR(30), MIN(t.StartTime)) + ' and ' + CONVERT(NVARCHAR(30), MAX(t.StartTime))
4073+
+ ' that lasted on average '
4074+
+ CONVERT(NVARCHAR(10), AVG(DATEDIFF(SECOND, t.StartTime, t.EndTime)))
4075+
+ ' seconds.' AS Details
4076+
FROM sys.fn_trace_gettable( @base_tracefilename, DEFAULT) AS t
4077+
WHERE t.EventClass IN (94, 95)
4078+
GROUP BY t.DatabaseName
4079+
HAVING AVG(DATEDIFF(SECOND, t.StartTime, t.EndTime)) > 5
4080+
4081+
END
4082+
38384083

38394084
IF @CheckUserDatabaseObjects = 1
38404085
BEGIN

0 commit comments

Comments
 (0)