Blog Post

Database Dropped

,

What do you do when a developer comes to you and asks, “Where did the database go?  The database was there one minute, and the next it was not.”  Only one thing could be database droppedworse than the feeling of losing a database on your watch, and that would be losing a production database. It’s like magic—it’s there, and then it disappears. To compound the issue, when asking people if they know what might have happened, all will typically deny, deny, deny.

What do you do when you run into that missing database situation and the inevitable denial that will ensue?  This is when an audit can save the day.  Through an audit, you can discover who dropped the database and when it happened.  Then you have hard data to take back to the team to again ask what happened.  Taking the info from a previous article of mine, we can alter the script I published there and re-use it for our needs here.

DECLARE @DBName sysname = 'AdventureWorks2014'
,@d1 DATETIME
,@diff INT;
SELECT ObjectName
  , ObjectID
  , DatabaseName
  , StartTime
  , EventClass
  , EventSubClass
  , ObjectType
  , ServerName
  , LoginName
  , NTUserName
  , ApplicationName
  , CASE EventClass
WHEN 46
THEN 'CREATE'
WHEN 47
THEN 'DROP'
--WHEN 164
--THEN 'ALTER'
END AS DDLOperation
INTO #temp_trace  
FROM sys.fn_trace_gettable(CONVERT(VARCHAR(150), 
( SELECT REVERSE(SUBSTRING(REVERSE(path),
CHARINDEX('',REVERSE(path)),256)) + 'log.trc'
FROM    sys.traces
WHERE   is_default = 1)), DEFAULT) T  
  WHERE EventClass in (46,47) 
AND EventSubclass = 0
AND ObjectType = 16964-- i just want database related events   
AND DatabaseName = ISNULL(@DBName,DatabaseName);

SELECT @d1 = MIN(StartTime) 
FROM #temp_trace;
SET @diff= DATEDIFF(hh,@d1,GETDATE());

SELECT @diff AS HrsSinceFirstChange    
, @d1 AS FirstChangeDate    
, sv.name AS obj_type_desc
, tt.ObjectType
, tt.DDLOperation
, tt.DatabaseName,tt.ObjectName,tt.StartTime
, tt.EventClass,tt.EventSubClass
, tt.ServerName,tt.LoginName, tt.NTUserName
, tt.ApplicationName
, (dense_rank() OVER (ORDER BY ObjectName,ObjectType ) )%2 AS l1     
, (dense_rank() OVER (ORDER BY ObjectName,ObjectType,StartTime ))%2 AS l2    
FROM #temp_trace tt
INNER JOIN sys.trace_events AS te 
ON tt.EventClass = te.trace_event_id
INNER JOIN sys.trace_subclass_values tsv
ON tt.EventClass = tsv.trace_event_id
AND tt.ObjectType = tsv.subclass_value
INNER JOIN master.dbo.spt_values sv 
ON tsv.subclass_value = sv.number
AND sv.type = 'EOD'
ORDER BY StartTime DESC;
DROP TABLE #temp_trace;

This script will now query the default trace to determine when a database was dropped or created.  I am limiting this result set through the use of this filter: ObjectType = 16964.  In addition to that, I have also trimmed the result-set down to just look for drop or create events.

This is the type of information that is already available within the default trace.  What if you wished to not be entirely dependent on the default trace for that information?  As luck would have it, you don’t need to be solely dependent on the default trace.  Instead you can use the robust tool called extended events.  If you would like to be able to take advantage of Extended Events to track this information, I recommend you read my follow-up article here.

This has been a republication of my original content first posted here.

Original post (opens in new tab)
View comments in original post (opens in new tab)

Rate

You rated this post out of 5. Change rating

Share

Share

Rate

You rated this post out of 5. Change rating