Як відфільтрувати використання сканованого користувачем функції з даних даних аудиту 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_idв WHEREреченні, але це наше сучасне мислення , як найкращим чином підійти до цієї проблеми. Чи є альтернативний підхід, який ми повинні врахувати?

Ми помітили, що коли скалярна функція використовується в рекурсивному 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.- Це один із найчудовіших побічних ефектів скалярних АДС, які я коли-небудь чув, і я чув багато.
— Ерік Дарлінг

3
Чи є можливість створити UDF, які ви не хочете перевіряти в окремій базі даних (що не перевіряється) та викликати їх через 3-частинну назву?
— Скотт Ходгін

@ScottHodgin, мені подобається вирішення, але в наших обставинах є кілька функцій зі скалярною оцінкою, які постачає постачальник, який ми не можемо видалити або перемістити до альтернативної бази даних.
— Марк Іаннуччі

Тим, хто слідує далі, може бути цікаво, який випадок викликає запит записувати в журнал аудиту для кожного рядка в наборі результатів; ми помітили, що це відбувається, коли скалярна функція використовується в рекурсивному КТЕ.
— Марк Іаннуччі

Відповіді:


6

Є кілька варіантів, над якими мені вдалося налагодити роботу. Усі параметри стосуються варіантів предикатів фільтрів. ПРИМІТКА. Ви повинні відключити аудит сервера, щоб внести зміни, а потім знову ввімкнути його.

По-перше, найбільш загальний підхід - це відфільтрувати всі скалярні АДС. Це можна зробити за допомогою class_typeполя аудиту. Документація вказує, що це поле є VARCHAR(2), але воно не дозволяє вказувати рядок. Однак я працював над цим:

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

(більше інформації про це розслідування тут: таємниця аудиту сервера: фільтрування class_type отримує помилку 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');

Хоча цей підхід не дуже загальний, цей підхід повинен бути прекрасним, оскільки кількість функцій для фільтрації має бути досить невеликою, і не дуже часто вводитимуться нові функції.

Нарешті, для інших, хто стикається з цією ситуацією і не обмежений внесенням змін: ви можете розмістити функції у власну схему, а потім відфільтрувати саме цю схему. Це більш загально, ніж фільтрувати функції окремо. Якщо припустити, що ви створили схему з назвою fnі помістите в неї функції (функції):

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

ТАКОЖ щодо наступних двох коментарів у питанні:

На жаль, SQL Server не дозволяє реляційний оператор IN (можливо, тому що він не хоче запитувати кожен раз, коли він повинен записувати в журнал аудиту).

і:

Ми хотіли б уникнути запису збереженої програми, яка жорстко кодує object_id в пункті WHERE

INОператор не є проблемою. Щоправда, він не підтримується, але це лише скорочення списку ORумов. Актуальною проблемою є використання T-SQL. Дозволені лише літерали - рядки чи цифри. Таким чином, ви б не змогли виконати збережену процедуру. Також не можна використовувати вбудовані функції.


дякую за цю відповідь Ми зараз впроваджуємо цю зміну, і я прийму цю відповідь, коли підтверджу, що вона працює в нашому середовищі.
— Марк Іаннуччі

1
@MarkIannucci Дякую! Крім того, я просто виправив незначну помилку в своїй ідеальній пропозиції. Я скопіював і вставив з тестування, де я фільтрував ЗА функції замість будь-яких функцій. Я змінив, =щоб бути <>у своїй відповіді. Я також просто перевірив це, і він працює, як рекламується :-)
— Соломон Руцький
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.