У нас есть база данных SQL Server, которая имеет спецификацию аудита базы данных, которая проверяет все выполняемые действия в базе данных.
CREATE DATABASE AUDIT SPECIFICATION [dbAudit]
FOR SERVER AUDIT [servAudit]
ADD (EXECUTE ON DATABASE::[DatabaseName] BY [public])
Мы обнаружили, что некоторые запросы записывают в журнал аудита использование скалярной функции для каждой строки в наборе результатов. Когда это происходит, журнал заполняется до того, как мы сможем поместить его в место последнего упокоения, и у нас есть пробел в нашем журнале.
К сожалению, из-за соображений соответствия, мы не можем просто прекратить проверку каждого EXECUTE
заявления.
Нашей первой мыслью о подходе к этой проблеме является использование WHERE
условия аудита сервера для фильтрации действий. Код выглядел так:
WHERE [object_id] not in (Select object_id from sys.objects where type = 'FN' )
К сожалению, SQL Server не допускает реляционный оператор IN (возможно, потому что он не хочет запрашивать каждый раз, когда ему нужно записать в журнал аудита).
Мы хотели бы избежать написания хранимого процесса, который жестко кодирует object_id
в WHERE
предложении, но это наш текущий взгляд на лучший способ решения этой проблемы. Есть ли альтернативный подход, который мы должны рассмотреть?
Мы заметили, что когда скалярная функция используется в рекурсивном CTE, она заставляет запрос записывать в журнал аудита для каждой строки в наборе результатов.
Существует несколько скалярных функций, предоставляемых поставщиком, которые мы не можем удалить или перенести в альтернативную базу данных.
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, которые я когда-либо слышал, и я много слышал.Ответы:
Есть несколько вариантов, с которыми я смог работать. Все опции имеют дело с вариациями предикатов фильтра. ПРИМЕЧАНИЕ. Чтобы внести изменения, необходимо отключить аудит сервера, а затем снова включить его.
Во-первых, наиболее общий подход состоит в том, чтобы отфильтровать все скалярные UDF. Вы можете сделать это, используя
class_type
поле аудита. В документации указано, что это поле естьVARCHAR(2)
, но оно не позволяет указывать строку. Тем не менее, я получил следующее для работы:(более подробная информация об этом расследовании здесь: Тайна аудита сервера: фильтрация class_type получает сообщение об ошибке 25713 )
Следующий наиболее общий подход - не вариант, поскольку было указано, что это база данных, предоставляемая поставщиком, и, следовательно, изменения не могут быть внесены. Так что я расскажу об этом последнем.
Наименее универсальный подход (но он определенно работает) - отфильтровать имя конкретной функции:
Или, если несколько имен:
Хотя этот подход не очень общий, он должен подойти, так как количество отфильтрованных функций должно быть довольно небольшим, и не так часто будут появляться новые функции.
Наконец, для тех, кто сталкивается с этой ситуацией и не имеет ограничений для внесения изменений: вы можете поместить функции в их собственную схему, а затем отфильтровать только эту схему. Это более общий характер, чем индивидуальная фильтрация функций. Предполагая, что вы создали именованную схему
fn
и поместили в нее функции:ТАКЖЕ, относительно следующих двух комментариев в вопросе:
и:
IN
Оператор не является проблемой. Правда, это не поддерживается, но это просто сокращение для спискаOR
условий. Актуальная проблема - использование T-SQL. Разрешены только литералы - строки или числа. Так что вы не смогли бы выполнить хранимую процедуру в любом случае. Также вы не можете использовать встроенные функции.источник
=
чтобы быть<>
в моем ответе. Я также только что проверил это, и это работает как рекламируется :-)