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 EXECUTE
Aussage zu prüfen .
Unser erster Gedanke zur Lösung dieses Problems ist die Verwendung der WHERE
Klausel 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_id
in der WHERE
Klausel 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.
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.Antworten:
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 istVARCHAR(2)
, jedoch keine Zeichenfolge angegeben werden kann. Allerdings habe ich Folgendes zum Laufen gebracht:(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:
Oder, wenn mehrere Namen:
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
fn
und platzieren die Funktion (en) darin:AUCH in Bezug auf die folgenden zwei Kommentare in der Frage:
und:
Der
IN
Bediener ist nicht das Problem. Es ist wahr, es wird nicht unterstützt, aber es ist nur eine Abkürzung für eine Liste vonOR
Bedingungen. 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.quelle
=
, um<>
in meiner Antwort zu sein. Ich habe es auch gerade getestet und es funktioniert wie angekündigt :-)