Herausfiltern der Verwendung von skalarwertigen benutzerdefinierten Funktionen aus SQL Server-Überwachungsdaten

12

Wir haben eine SQL Server-Datenbank mit einer Datenbankprüfspezifikation, die alle ausgeführten Aktionen auf der Datenbank prüft.

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

Wir haben festgestellt, dass einige Abfragen die Verwendung einer Skalarfunktion für jede Zeile in einer Ergebnismenge in das Überwachungsprotokoll schreiben. In diesem Fall füllt sich das Protokoll, bevor wir es in seine letzte Ruhestätte ETL können, und wir haben eine Lücke in der Protokollierung.

Leider können wir aus Compliance-Gründen nicht einfach aufhören, jede EXECUTEAussage zu prüfen .

Unser erster Gedanke zur Lösung dieses Problems ist die Verwendung der WHEREKlausel in der Serverüberwachung , um die Aktivität herauszufiltern. Der Code sah folgendermaßen aus:

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

Leider lässt SQL Server keinen relationalen IN-Operator zu (wahrscheinlich, weil nicht jedes Mal abgefragt werden soll, wenn in das Überwachungsprotokoll geschrieben werden muss).

Wir möchten es vermeiden, einen gespeicherten Proc zu schreiben, der das object_idin der WHEREKlausel fest codiert , aber das ist unsere derzeitige Überlegung, wie wir dieses Problem am besten angehen können. Gibt es einen alternativen Ansatz, den wir berücksichtigen sollten?

Wir haben festgestellt, dass bei Verwendung der Skalarfunktion in einem rekursiven CTE die Abfrage für jede Zeile in der Ergebnismenge in das Überwachungsprotokoll geschrieben wird.

Es gibt einige skalare Funktionen, die von einem Anbieter bereitgestellt werden und die nicht gelöscht oder in eine alternative Datenbank verschoben werden können.

Mark Iannucci
quelle
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.- Das ist einer der großartigsten Nebenwirkungen von skalaren UDFs, die ich je gehört habe, und ich habe viel gehört.
Erik Darling
3
Gibt es eine Möglichkeit, UDFs, die nicht geprüft werden sollen, in einer separaten Datenbank (die nicht geprüft werden soll) zu erstellen und über einen dreiteiligen Namen aufzurufen?
Scott Hodgin
@ScottHodgin, ich mag die Problemumgehung, aber unter unseren Umständen gibt es einige skalare Funktionen, die von einem Anbieter geliefert werden und die wir nicht löschen oder in eine alternative Datenbank verschieben können.
Mark Iannucci
Die folgenden Personen fragen sich möglicherweise, in welchem ​​Fall die Abfrage für jede Zeile in einer Ergebnismenge in das Überwachungsprotokoll schreibt. Wir haben festgestellt, dass dies auftritt, wenn die Skalarfunktion in einem rekursiven CTE verwendet wird.
Mark Iannucci

Antworten:

6

Es gibt ein paar Möglichkeiten, die ich nutzen konnte. Alle Optionen befassen sich mit Variationen von Filterprädikaten. ANMERKUNG: Sie müssen die Serverüberwachung deaktivieren , um Änderungen vornehmen zu können, und sie dann erneut aktivieren .

Erstens besteht der allgemeinste Ansatz darin, alle Scalar-UDFs herauszufiltern. Sie können das tun, indem Sie das class_typeÜberwachungsfeld verwenden. Aus der Dokumentation geht hervor, dass dieses Feld zwar vorhanden ist VARCHAR(2), jedoch keine Zeichenfolge angegeben werden kann. Allerdings habe ich Folgendes zum Laufen gebracht:

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

(Weitere Informationen zu dieser Untersuchung finden Sie hier: Server Audit Mystery: Beim Filtern von class_type wird der Fehler Msg 25713 angezeigt. )

Der nächst allgemeinere Ansatz ist keine Option, da angegeben wurde, dass es sich um eine vom Hersteller bereitgestellte Datenbank handelt und daher keine Änderungen vorgenommen werden können. Also werde ich das letzte behandeln.

Der am wenigsten generische Ansatz (der aber definitiv funktioniert) ist das Herausfiltern des spezifischen Funktionsnamens:

ALTER SERVER AUDIT [servAudit]
WHERE ([object_name]<>'function_name');

Oder, wenn mehrere Namen:

ALTER SERVER AUDIT [servAudit]
WHERE ([object_name]<>'function_name1' AND [object_name]<>'function_name2');

Obwohl dies nicht sehr allgemein ist, sollte dieser Ansatz in Ordnung sein, da die Anzahl der herauszufilternden Funktionen relativ gering sein sollte und es nicht sehr oft vorkommt, dass neue Funktionen eingeführt werden.

Zu guter Letzt, für andere, die mit dieser Situation konfrontiert sind und nicht daran gehindert sind, Änderungen vorzunehmen: Sie können Funktionen in ihr eigenes Schema einfügen und dann nur dieses Schema herausfiltern. Dies ist allgemeiner, als die Funktionen einzeln herauszufiltern. Angenommen, Sie erstellen ein Schema mit dem Namen fnund platzieren die Funktion (en) darin:

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

AUCH in Bezug auf die folgenden zwei Kommentare in der Frage:

Leider lässt SQL Server keinen relationalen IN-Operator zu (wahrscheinlich, weil nicht jedes Mal abgefragt werden soll, wenn in das Überwachungsprotokoll geschrieben werden muss).

und:

Wir möchten vermeiden, einen gespeicherten Prozess zu schreiben, der die object_id in der WHERE-Klausel fest codiert

Der INBediener ist nicht das Problem. Es ist wahr, es wird nicht unterstützt, aber es ist nur eine Abkürzung für eine Liste von ORBedingungen. Das eigentliche Problem ist die Verwendung von T-SQL. Es sind nur Literale - Zeichenfolgen oder Zahlen - zulässig. Sie hätten also ohnehin keine gespeicherte Prozedur ausführen können. Sie können die integrierten Funktionen auch nicht verwenden.

Solomon Rutzky
quelle
Vielen Dank für diese Antwort. Wir sind dabei, diese Änderung umzusetzen, und ich werde diese Antwort akzeptieren, wenn wir bestätigen, dass sie in unserer Umgebung funktioniert.
Mark Iannucci
1
@MarkIannucci Danke! Außerdem habe ich gerade einen kleinen Fehler in meinem idealen Vorschlag behoben. Ich hatte von Tests kopiert und eingefügt, bei denen ich FOR-Funktionen anstelle von ALLES-ABER-Funktionen filterte. Ich änderte das =, um <>in meiner Antwort zu sein. Ich habe es auch gerade getestet und es funktioniert wie angekündigt :-)
Solomon Rutzky