web-dev-qa-db-fra.com

Utilisation d'un événement étendu pour suivre les mises à jour d'une table

J'ai un tableau qui ne cesse de se mettre à jour, et personne ne peut savoir d'où viennent les mises à jour. Je soupçonne qu'ils proviennent d'Entity Framework, mais je veux capturer la MISE À JOUR et les informations associées via un événement étendu pour prouver cette théorie.

Je suis sur SQL 2014 Enterprise et j'essaie de capturer ces informations à l'aide des événements exec_prepared_sql et sql_statement_starting. Voici ce que j'ai jusqu'à présent:

CREATE EVENT SESSION [Query Trace] ON SERVER 
ADD EVENT sqlserver.exec_prepared_sql(
    ACTION(sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.database_id,sqlserver.database_name,sqlserver.plan_handle,sqlserver.session_id,sqlserver.sql_text,sqlserver.username)
    WHERE ([sqlserver].[like_i_sql_unicode_string]([sqlserver].[sql_text],N'%UPDATE %') AND [sqlserver].[like_i_sql_unicode_string]([sqlserver].[sql_text],N'%TableA%') AND [sqlserver].[database_id]=(123))),
ADD EVENT sqlserver.sql_statement_starting(
    ACTION(sqlserver.client_app_name,sqlserver.client_hostname,sqlserver.database_id,sqlserver.database_name,sqlserver.plan_handle,sqlserver.session_id,sqlserver.sql_text,sqlserver.username)
    WHERE ([sqlserver].[like_i_sql_unicode_string]([sqlserver].[sql_text],N'%UPDATE %') AND [sqlserver].[like_i_sql_unicode_string]([sqlserver].[sql_text],N'%TableA%') AND [sqlserver].[database_id]=(123)))
ADD TARGET package0.event_file(SET filename=N'E:\ExtendedEvent\Query-Trace.xel')
WITH (MAX_MEMORY=4096 KB,EVENT_RETENTION_MODE=ALLOW_SINGLE_EVENT_LOSS,MAX_DISPATCH_LATENCY=30 SECONDS,MAX_EVENT_SIZE=0 KB,MEMORY_PARTITION_MODE=NONE,TRACK_CAUSALITY=ON,STARTUP_STATE=OFF)
GO

Cela semble bien fonctionner, je l'ai testé et j'ai pu capturer à la fois une instruction UPDATE régulière et une appelée avec sp_executesql. Cependant, il me manque encore quelque chose. Les données de la table sont toujours en cours de modification et cet événement étendu ne capture pas la mise à jour qui le fait.

Donc, mes questions sont:

1) Y a-t-il autre chose que je dois surveiller dans mon événement étendu afin de capturer les MISES À JOUR provenant éventuellement d'Entity Framework?

2) Y a-t-il autre chose que je devrais utiliser à la place des événements étendus pour cela?

Merci!

7
Eric Cobb

Lorsque vous utilisez SQL Server Enterprise Edition (ou exécutez une édition plus récente que 2016 SP1), je recommanderais d'utiliser la fonctionnalité SQLAudit. Cela vous donnera de très bonnes informations détaillées sur qui touche vos tables et les commandes en cours d'exécution.

Pour quelque chose comme ça, vous voudriez utiliser un spécification d'audit de base de données avec un audit du serveur (utilisé pour définir où votre audit écrira), puis l'étendre jusqu'à la table que vous souhaitez surveiller. D'ici là, les modifications de portée du rôle public vous permettront de capturer tous les changements qui se produisent.

Ce script devrait vous y amener (testez dans votre environnement de développement et remplacez les éléments pertinents pour les tables que vous souhaitez surveiller).

USE [master]

GO

CREATE SERVER AUDIT [Audit-TblChanges]
TO FILE 
(   FILEPATH = N'C:\SQLAudit'
    ,MAXSIZE = 0 MB
    ,MAX_ROLLOVER_FILES = 2147483647
    ,RESERVE_DISK_SPACE = OFF
)
WITH
(   QUEUE_DELAY = 1000
    ,ON_FAILURE = CONTINUE
)

GO

USE [YourDatabase]
GO

CREATE DATABASE AUDIT SPECIFICATION [DatabaseAuditSpecification-MyTable]
FOR SERVER AUDIT [Audit-TblChanges]
ADD (UPDATE ON OBJECT::[YourTable] BY [public]),
ADD (INSERT ON OBJECT::[YourTable] BY [public])

GO


USE [master]
GO
ALTER SERVER AUDIT [Audit-TblChanges] WITH (STATE = ON);

USE [YourDatabase]
GO
ALTER DATABASE AUDIT SPECIFICATION [DatabaseAuditSpecification-MyTable] WITH (STATE = ON);
GO

Vous pouvez lire rapidement les données à l'aide de l'interface graphique ou utiliser sys.fn_get_audit_file pour interroger les données directement à partir de SQL Server.

9
Nic