在我們的一個SQL Server數據庫中,我們有很多SQL視圖。一個特定的觀點每隔幾個星期就會消失,我想知道發生了什麼。查找SQL Server中SQL視圖被刪除的人員/時間
有沒有辦法查詢SQL Server來找出何時和誰刪除視圖?
或者,是否可以在DROP
視圖命令中添加SQL Server觸發器以捕獲並失敗DROP
?
在我們的一個SQL Server數據庫中,我們有很多SQL視圖。一個特定的觀點每隔幾個星期就會消失,我想知道發生了什麼。查找SQL Server中SQL視圖被刪除的人員/時間
有沒有辦法查詢SQL Server來找出何時和誰刪除視圖?
或者,是否可以在DROP
視圖命令中添加SQL Server觸發器以捕獲並失敗DROP
?
是的,這是一個DDL觸發器。 MSDN文章中包含有關此類觸發器的示例觸發器文本。出於審計原因,我認爲這樣的觸發器是生產數據庫中的必需品。
https://technet.microsoft.com/en-us/library/ms187909.aspx
另一個技巧是創建依賴這個對象(視圖)另一個對象(圖?)和SCHEMA_BINDING
選項上。這將使不可能放棄任何對象架構綁定對象依賴。
將此信息寫入默認跟蹤。以下是收集信息的示例查詢。
SELECT
te.name
,tt.DatabaseName
,tt.StartTime
,tt.HostName
,tt.LoginName
,tt.ApplicationName
,tt.LoginName
FROM sys.traces AS t
CROSS APPLY fn_trace_gettable(
--get trace folder and add base file name log.trc
REVERSE(SUBSTRING(REVERSE(t.path), CHARINDEX(N'\', REVERSE(t.path)), 128)) + 'log.trc', default) AS tt
JOIN sys.trace_events AS te ON
te.trace_event_id = tt.EventClass
JOIN sys.trace_subclass_values AS tesv ON
tesv.trace_event_id = tt.EventClass
AND tesv.subclass_value = tt.EventSubClass
WHERE
t.is_default = 1 --default trace
AND tt.ObjectName = N'YourView'
AND tt.DatabaseName = N'YourDatabase';
注意默認跟蹤是保持最大100MB,因此它可能沒有法醫的信息,如果該觀點在不久前重新翻滾的痕跡。
謝謝,這讓我更靠近了一步。該查詢顯示該視圖在幾天前被刪除,並通過哪個登錄和哪個應用程序。 –
要展開另一個答案,下面是一些代碼,以便開始使用DROP_VIEW
的DDL觸發器。舉一個例子,假設有人從AdventureWorks
數據庫中刪除了視圖[HumanResources].[vEmployee]
。該EVENTDATA()
會是這個樣子:
<EVENT_INSTANCE>
<EventType>DROP_VIEW</EventType>
<PostTime>2016-02-26T09:02:58.190</PostTime>
<SPID>60</SPID>
<ServerName>YourSqlHost\SQLEXPRESS</ServerName>
<LoginName>YourDomain\SomeLogin</LoginName>
<UserName>dbo</UserName>
<DatabaseName>AdventureWorks2012</DatabaseName>
<SchemaName>HumanResources</SchemaName>
<ObjectName>vEmployee</ObjectName>
<ObjectType>VIEW</ObjectType>
<TSQLCommand>
<SetOptions ANSI_NULLS="ON" ANSI_NULL_DEFAULT="ON" ANSI_PADDING="ON" QUOTED_IDENTIFIER="ON" ENCRYPTED="FALSE" />
<CommandText>DROP VIEW [HumanResources].[vEmployee]
</CommandText>
</TSQLCommand>
</EVENT_INSTANCE>
這裏是一個可能的DDL觸發器聲明:
CREATE TRIGGER trgDropView
ON DATABASE
FOR DROP_VIEW
AS
BEGIN
--Grab some pertinent items from EVENTDATA()
DECLARE @LoginName NVARCHAR(MAX) = EVENTDATA().value('(/EVENT_INSTANCE/LoginName)[1]', 'NVARCHAR(MAX)')
DECLARE @TsqlCmd NVARCHAR(MAX) = EVENTDATA().value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','NVARCHAR(MAX)')
--Now do something. Lots of possibilities. Here are two:
--1) Send Email
DECLARE @Subj NVARCHAR(255) = @@SERVERNAME + ' - VIEW DROPPED'
DECLARE @MsgBody NVARCHAR(255) = 'Login Name: ' + @LoginName + CHAR(13) + CHAR(10) +
'Command: ' + @TsqlCmd
EXEC msdb..sp_send_dbmail
@recipients = '[email protected]',
@subject = @Subj,
@body = @MsgBody
--2) Log an error
DECLARE @ErrMsg NVARCHAR(MAX) = @@SERVERNAME + ' - VIEW DROPPED' + CHAR(13) + CHAR(10) +
'Login Name: ' + @LoginName + CHAR(13) + CHAR(10) +
'Command: ' + @TsqlCmd
RAISERROR(@ErrMsg, 16, 1) WITH LOG;
END
你也可以爲了捕捉和記錄DDL變化創造trigger在服務器級別數據庫:
CREATE TRIGGER [Trg_AuditStoredProcedures_Data]
ON ALL SERVER
FOR CREATE_PROCEDURE,ALTER_PROCEDURE,DROP_PROCEDURE,CREATE_TABLE,ALTER_TABLE,
DROP_TABLE,CREATE_FUNCTION,ALTER_FUNCTION,DROP_FUNCTION,CREATE_VIEW,ALTER_VI EW,
DROP_VIEW,CREATE_DATABASE,DROP_DATABASE,ALTER_DATABASE,
CREATE_TRIGGER,DROP_TRIGGER,ALTER_TRIGGER
AS
SET ANSI_PADDING ON
DECLARE @eventdata XML;
SET @eventdata = EVENTDATA();
SET NOCOUNT ON
/*Create table AuditDatabaseObject in order to have a history tracking for every DDL change on the database*/
INSERT INTO AuditDatabaseObject
(DatabaseName,ObjectName,LoginName,ChangeDate,EventType,EventDataXml,HostName)
VALUES (
@eventdata.value('(/EVENT_INSTANCE/DatabaseName)[1]','sysname')
, @eventdata.value('(/EVENT_INSTANCE/ObjectName)[1]', 'sysname')
, @eventdata.value('(/EVENT_INSTANCE/LoginName)[1]', 'sysname')
, GETDATE()
, @eventdata.value('(/EVENT_INSTANCE/EventType)[1]', 'sysname')
, @eventdata
, HOST_NAME()
);
DECLARE @Valor VARCHAR(30),@EvenType VARCHAR(30)
SET @Valor = @eventdata.value('(/EVENT_INSTANCE/LoginName)[1]', 'sysname')
SET @EvenType = @eventdata.value('(/EVENT_INSTANCE/EventType)[1]', 'sysname')
IF (IS_SRVROLEMEMBER('sysadmin',@Valor) != 1 AND @EvenType = 'DROP_DATABASE')
BEGIN
ROLLBACK
END
,你可以在這裏找到更多的信息EVENTDATA()
如果一個對象被從數據庫中刪除,你會看到在桌子上創造了一項紀錄AuditDatabaseObject
也牢記安全爲@克里斯·皮克福德提及。
問自己一個問題,「誰需要能夠刪除數據庫對象?」。限制你的數據庫對這些人/帳戶的權限。 –
我爲此開始了一項服務[dbhistory.com](http://dbhistory.com)。 –