Skip to content

Commit 6825c6e

Browse files
committed
Merge remote-tracking branch 'refs/remotes/origin/dev'
2 parents fb55c5e + 8889090 commit 6825c6e

File tree

4 files changed

+512
-136
lines changed

4 files changed

+512
-136
lines changed

sp_Blitz.sql

Lines changed: 250 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -506,13 +506,6 @@ AS
506506
INSERT INTO #IgnorableWaits VALUES ('XE_DISPATCHER_WAIT');
507507
INSERT INTO #IgnorableWaits VALUES ('XE_LIVE_TARGET_TVF');
508508
INSERT INTO #IgnorableWaits VALUES ('XE_TIMER_EVENT');
509-
510-
511-
/* Used for the default trace checks. */
512-
DECLARE @TracePath NVARCHAR(256);
513-
SELECT @TracePath=CAST(value as NVARCHAR(256))
514-
FROM sys.fn_trace_getinfo(1)
515-
WHERE traceid=1 AND property=2;
516509

517510
SELECT @MsSinceWaitsCleared = DATEDIFF(MINUTE, create_date, CURRENT_TIMESTAMP) * 60000.0
518511
FROM sys.databases
@@ -3061,7 +3054,7 @@ AS
30613054
IF NOT EXISTS ( SELECT 1
30623055
FROM #SkipChecks
30633056
WHERE DatabaseName IS NULL AND CheckID = 150 )
3064-
AND @TracePath IS NOT NULL
3057+
AND @base_tracefilename IS NOT NULL
30653058
BEGIN
30663059

30673060
INSERT INTO #BlitzResults
@@ -3080,7 +3073,7 @@ AS
30803073
'Errors Logged Recently in the Default Trace' AS Finding ,
30813074
'https://BrentOzar.com/go/defaulttrace' AS URL ,
30823075
CAST(t.TextData AS NVARCHAR(4000)) AS Details
3083-
FROM sys.fn_trace_gettable(@TracePath, DEFAULT) t
3076+
FROM sys.fn_trace_gettable(@base_tracefilename, DEFAULT) t
30843077
WHERE t.EventClass = 22
30853078
AND t.Severity >= 17
30863079
AND t.StartTime > DATEADD(dd, -30, GETDATE())
@@ -3091,7 +3084,7 @@ AS
30913084
IF NOT EXISTS ( SELECT 1
30923085
FROM #SkipChecks
30933086
WHERE DatabaseName IS NULL AND CheckID = 151 )
3094-
AND @TracePath IS NOT NULL
3087+
AND @base_tracefilename IS NOT NULL
30953088
BEGIN
30963089
INSERT INTO #BlitzResults
30973090
( CheckID ,
@@ -3109,7 +3102,7 @@ AS
31093102
'File Growths Slow' AS Finding ,
31103103
'https://BrentOzar.com/go/filegrowth' AS URL ,
31113104
CAST(COUNT(*) AS NVARCHAR(100)) + ' growths took more than 15 seconds each. Consider setting file autogrowth to a smaller increment.' AS Details
3112-
FROM sys.fn_trace_gettable(@TracePath, DEFAULT) t
3105+
FROM sys.fn_trace_gettable(@base_tracefilename, DEFAULT) t
31133106
WHERE t.EventClass IN (92, 93)
31143107
AND t.StartTime > DATEADD(dd, -30, GETDATE())
31153108
AND t.Duration > 15000000
@@ -3180,7 +3173,7 @@ AS
31803173
AND cTotal.counter_name = N'Total Server Memory (KB) '
31813174
WHERE cFree.object_name LIKE N'%Memory Manager%'
31823175
AND cFree.counter_name = N'Free Memory (KB) '
3183-
AND CAST(cTotal.cntr_value AS BIGINT) > 4000
3176+
AND CAST(cTotal.cntr_value AS BIGINT) > 20480000000
31843177
AND CAST(cTotal.cntr_value AS BIGINT) * .3 <= CAST(cFree.cntr_value AS BIGINT)
31853178
AND CAST(SERVERPROPERTY('edition') AS VARCHAR(100)) NOT LIKE '%Standard%'
31863179

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

38433836
END;
38443837

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+
38454083

38464084
IF @CheckUserDatabaseObjects = 1
38474085
BEGIN

0 commit comments

Comments
 (0)