Sql-Server

如何從 SQL Server 審計數據中過濾掉標量值使用者定義函式的使用情況?

  • January 23, 2018

我們有一個 SQL Server 數據庫,它有一個數據庫審計規範,它審計數據庫上的所有執行操作。

CREATE DATABASE AUDIT SPECIFICATION [dbAudit]
FOR SERVER AUDIT [servAudit]
ADD (EXECUTE ON DATABASE::[DatabaseName] BY [public])

我們發現,一些查詢會將結果集中每一行的標量函式寫入審計日誌。發生這種情況時,日誌會在我們將其 ETL 到它的最終休息位置之前填滿,並且我們的日誌記錄中存在間隙。

不幸的是,由於合規原因,我們不能簡單地停止審核每一個EXECUTE報表。

我們解決這個問題的第一個想法是使用Server AuditWHERE上的子句來過濾掉活動。程式碼如下所示:

WHERE [object_id] not in (Select object_id from sys.objects where type = 'FN' )

不幸的是,SQL Server 不允許關係型 IN 運算符(可能是因為它不想在每次寫入審計日誌時都進行查詢)。

我們希望避免編寫object_idWHERE子句中硬編碼的儲存過程,但這是我們目前對解決此問題的最佳方法的想法。我們應該考慮另一種方法嗎?

我們注意到,當標量函式在遞歸 CTE 中使用時,它會導致查詢為結果集中的每一行寫入審計日誌。

供應商提供了一些標量值函式,我們無法將其刪除或移動到備用數據庫。

有幾個選項我可以開始工作。所有選項都處理過濾謂詞的變體。**注意:**您必須禁用伺服器審核才能進行更改,然後重新啟用它。

首先,最通用的方法是過濾掉所有標量 UDF。您可以通過使用class_type審計欄位來做到這一點。文件表明該欄位是VARCHAR(2),但它不允許指定字元串。但是,我確實得到了以下工作:

ALTER SERVER AUDIT [servAudit]
WHERE ([class_type] <> 20038); -- EXECUTE Scalar UDF

(有關該調查的更多資訊:Server Audit Mystery: Filtering class_type gets Error Msg 25713

下一個最通用的方法不是一個選項,因為它聲明這是一個供應商提供的數據庫,因此不能進行任何更改。所以我將在最後介紹。

最不通用的方法(但絕對有效的方法)是過濾掉特定的函式名稱:

ALTER SERVER AUDIT [servAudit]
WHERE ([object_name]<>'function_name');

或者,如果有多個名稱:

ALTER SERVER AUDIT [servAudit]
WHERE ([object_name]<>'function_name1' AND [object_name]<>'function_name2');

雖然不是很通用,但這種方法應該沒問題,因為要過濾掉的函式數量應該相當少,並且不會經常引入新函式。

最後,對於面臨這種情況且不受限制進行更改的其他人:您可以將函式放入他們自己的 Schema 中,然後僅過濾掉該 Schema。這比單獨過濾掉函式更通用。假設您創建了一個名為 Schema 並將fn函式放入其中:

ALTER SERVER AUDIT [servAudit]
WHERE ([schema_name]<>'fn');

另外,關於問題中的以下兩條評論:

不幸的是,SQL Server 不允許關係型 IN 運算符(可能是因為它不想在每次寫入審計日誌時都進行查詢)。

和:

我們希望避免編寫儲存過程,在 WHERE 子句中硬編碼 object_id

IN運營商不是問題。誠然,它不受支持,但它只是OR條件列表的簡寫。實際問題是 T-SQL 的使用。只允許使用文字——字元串或數字。因此,無論如何您都無法執行儲存過程。你也不能使用內置函式。

引用自:https://dba.stackexchange.com/questions/195199