如何从SQL Server审核数据中筛选出标量值用户定义的函数用法?


12

我们有一个SQL Server数据库,该数据库具有数据库审核规范,该规范审核数据库上所有执行的操作。

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

我们发现,某些查询将对结果集中的每一行使用标量函数写入审核日志。当发生这种情况时,在将日志ETL放入最终的静止位置之前,日志已填满,并且日志记录中存在空白。

不幸的是,由于合规性原因,我们不能简单地停止审核每条EXECUTE声明。

解决此问题的方法首先想到的是使用WHERE服务器审核”上的子句来过滤活动。代码如下所示:

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

不幸的是,SQL Server不允许使用关系IN运算符(可能是因为它不想在每次必须写入审核日志时都进行查询)。

我们想避免编写一个存储过程,其硬代码object_idWHERE条款,但是这是我们在解决这个问题的最好办法目前的想法。我们是否应该考虑替代方法?

我们注意到,当在递归CTE中使用标量函数时,它将导致查询将查询写入结果集中的每一行。

供应商提供了一些标量值函数,我们无法删除或移动到备用数据库。


6
We've found that some queries will write to the audit log the use of a scalar function for every row in a result set.-这是我所听过的标量UDF的最宏伟的副作用之一,而且我已经听到很多。
埃里克·达令

3
是否可以选择创建您不想在单独的数据库中进行审核(未审核)的UD​​F,然后通过三部分名称调用它们?
Scott Hodgin '18年

@ScottHodgin,我喜欢解决方法,但是在我们的情况下,供应商提供了一些标量值函数,我们无法删除它们或将其移至备用数据库。
Mark Iannucci

那些随后的读者可能想知道是什么情况导致查询针对结果集中的每一行写入审计日志。我们注意到在递归CTE中使用标量函数时会发生这种情况。
Mark Iannucci '18

Answers:


6

我有几个可以上班的选择。所有选项都处理过滤谓词的变体。注意:必须先禁用服务器审核才能进行更改,然后重新启用它。

首先,最通用的方法是过滤掉所有标量UDF。您可以通过使用class_type审核字段来做到这一点。文档指出此字段为VARCHAR(2),但不允许指定字符串。但是,我确实得到了以下工作:

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

(有关该调查的更多信息,请参见服务器审核之谜:过滤class_type收到错误消息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。仅允许使用文字(字符串或数字)。因此,无论如何您将无法执行存储过程。也不能使用内置功能。


感谢您的回复。我们正在实施此更改,当我们确认此更改在我们的环境中有效时,我将接受此答案。
Mark Iannucci

1
@MarkIannucci谢谢!另外,我只是在我的理想建议中修复了一个小错误。我从测试中复制并粘贴了我过滤FOR函数而不是任何其他函数的测试。我换了=<>我的回答。我也刚刚对其进行了测试,它的工作方式如广告所示:-)
Solomon Rutzky
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.