如何從 SQL Server 審計數據中過濾掉標量值使用者定義函式的使用情況?
我們有一個 SQL Server 數據庫,它有一個數據庫審計規範,它審計數據庫上的所有執行操作。
CREATE DATABASE AUDIT SPECIFICATION [dbAudit] FOR SERVER AUDIT [servAudit] ADD (EXECUTE ON DATABASE::[DatabaseName] BY [public])
我們發現,一些查詢會將結果集中每一行的標量函式寫入審計日誌。發生這種情況時,日誌會在我們將其 ETL 到它的最終休息位置之前填滿,並且我們的日誌記錄中存在間隙。
不幸的是,由於合規原因,我們不能簡單地停止審核每一個
EXECUTE
報表。我們解決這個問題的第一個想法是使用Server Audit
WHERE
上的子句來過濾掉活動。程式碼如下所示:WHERE [object_id] not in (Select object_id from sys.objects where type = 'FN' )
不幸的是,SQL Server 不允許關係型 IN 運算符(可能是因為它不想在每次寫入審計日誌時都進行查詢)。
我們希望避免編寫
object_id
在WHERE
子句中硬編碼的儲存過程,但這是我們目前對解決此問題的最佳方法的想法。我們應該考慮另一種方法嗎?我們注意到,當標量函式在遞歸 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 的使用。只允許使用文字——字元串或數字。因此,無論如何您都無法執行儲存過程。你也不能使用內置函式。