Як відфільтрувати використання сканованого користувачем функції з даних даних аудиту 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.