Question

Comment puis-je surveiller une base de données SQL Server pour détecter les modifications apportées à une table sans utiliser de déclencheurs ni modifier la structure de la base de données de quelque manière que ce soit ?Mon environnement de programmation préféré est .FILET et C#.

J'aimerais pouvoir soutenir n'importe qui SQL Serveur 2000 SP4 ou plus récent.Mon application est une visualisation de données intégrée pour le produit d'une autre entreprise.Notre clientèle se compte par milliers, je ne veux donc pas avoir à exiger que nous modifiions la table du fournisseur tiers à chaque installation.

Par "modifications d'une table" Je veux dire les modifications apportées aux données de la table, pas les modifications apportées à la structure de la table.

En fin de compte, j'aimerais que le changement déclenche un événement dans mon application, au lieu d'avoir à vérifier les changements à intervalles réguliers.


La meilleure solution compte tenu de mes besoins (pas de déclencheurs ni de modification de schéma, SQL Server 2000 et 2005) semble être d'utiliser le BINARY_CHECKSUM fonctionner dans T-SQL.La façon dont je prévois de mettre en œuvre est la suivante :

Toutes les X secondes, exécutez la requête suivante :

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*))
FROM sample_table
WITH (NOLOCK);

Et comparez cela à la valeur stockée.Si la valeur a changé, parcourez le tableau ligne par ligne à l'aide de la requête :

SELECT row_id, BINARY_CHECKSUM(*)
FROM sample_table
WITH (NOLOCK);

Et comparez les sommes de contrôle renvoyées avec les valeurs stockées.

Était-ce utile?

La solution

Jetez un œil à la commande CHECKSUM :

SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM sample_table WITH (NOLOCK);

Cela renverra le même numéro à chaque exécution tant que le contenu de la table n'a pas changé.Voir mon article à ce sujet pour plus d'informations :

SOMME DE CONTRÔLE

Voici comment je l'ai utilisé pour reconstruire les dépendances du cache lorsque les tables ont changé :
Dépendance du cache de base de données ASP.NET 1.1 (sans déclencheurs)

Autres conseils

Malheureusement, CHECKSUM ne fonctionne pas toujours correctement pour détecter les changements..

Il s'agit uniquement d'une somme de contrôle primitive et d'aucun calcul de contrôle de redondance cyclique (CRC).

Par conséquent, vous ne pouvez pas l'utiliser pour détecter tous les changements, par ex.g.des changements symétriques aboutissent au même CHECKSUM !

E.g.la solution avec CHECKSUM_AGG(BINARY_CHECKSUM(*)) fournira toujours 0 pour les 3 tables avec un contenu différent :


SELECT CHECKSUM_AGG(BINARY_CHECKSUM(*)) FROM 
(
  SELECT 1 as numA, 1 as numB
  UNION ALL
  SELECT 1 as numA, 1 as numB
)  q
-- delivers 0!

Sélectionnez Checksum_agg (binary_checksum (*)) depuis (sélectionnez 1 comme numa, 2 comme un syndicat engourdie tous sélectionnez 1 comme numa, 2 comme numb) q - délivre 0!

Sélectionnez Checksum_agg (binary_checksum (*)) From (Select 0 As numa, 0 As Numb Union tous SELECT 0 AS NUMA, 0 As Numb) Q - délivre 0!

Pourquoi ne voulez-vous pas utiliser de déclencheurs ?C’est une bonne chose si vous les utilisez correctement.Si vous les utilisez comme moyen de renforcer l’intégrité référentielle, c’est à ce moment-là qu’ils passent du bon au mauvais.Mais si vous les utilisez à des fins de surveillance, ils ne sont pas vraiment considérés comme tabous.

À quelle fréquence devez-vous vérifier les modifications et quelle est la taille (en termes de taille de ligne) des tables de la base de données ?Si vous utilisez le CHECKSUM_AGG(BINARY_CHECKSUM(*)) méthode suggérée par John, il analysera chaque ligne de la table spécifiée.Le NOLOCK un indice aide, mais sur une grande base de données, vous frappez toujours chaque ligne.Vous devrez également stocker la somme de contrôle pour chaque ligne afin de pouvoir indiquer qu'une d'entre elles a changé.

Avez-vous envisagé d’aborder la question sous un angle différent ?Si vous ne souhaitez pas modifier le schéma pour ajouter des déclencheurs (ce qui est logique, ce n'est pas votre base de données), avez-vous envisagé de travailler avec le fournisseur d'applications qui crée la base de données ?

Ils pourraient implémenter une API fournissant un mécanisme permettant d’informer les applications accessoires que les données ont été modifiées.Cela peut être aussi simple que d'écrire dans une table de notification qui répertorie quelle table et quelle ligne ont été modifiées.Cela pourrait être implémenté via des déclencheurs ou du code d’application.De votre côté, cela n'aurait pas d'importance, votre seul souci serait de scanner périodiquement le tableau de notifications.Les performances de la base de données seraient bien inférieures à l'analyse de chaque ligne à la recherche de modifications.

Le plus difficile serait de convaincre l’éditeur de l’application d’implémenter cette fonctionnalité.Étant donné que cela peut être entièrement géré via SQL via des déclencheurs, vous pouvez effectuer l'essentiel du travail à leur place en écrivant et en testant les déclencheurs, puis en apportant le code au fournisseur de l'application.En demandant au fournisseur de prendre en charge les déclencheurs, vous évitez la situation dans laquelle votre ajout d'un déclencheur remplace par inadvertance un déclencheur fourni par le fournisseur.

Malheureusement, je ne pense pas qu'il existe un moyen propre de procéder dans SQL2000.Si vous limitez vos exigences à SQL Server 2005 (et versions ultérieures), alors vous êtes en affaires.Vous pouvez utiliser le SQLDependency classe dans System.Data.SqlClient.Voir Notifications de requête dans SQL Server (ADO.NET).

Avoir un travail DTS (ou un travail démarré par un service Windows) qui s'exécute à un intervalle donné.Chaque fois qu'il est exécuté, il obtient des informations sur la table donnée en utilisant le système INFORMATION_SCHEMA tableaux et enregistre ces données dans le référentiel de données.Comparez les données renvoyées concernant la structure de la table avec les données renvoyées la fois précédente.Si c’est différent, alors vous savez que la structure a changé.

Exemple de requête pour renvoyer des informations sur toutes les colonnes de la table ABC (idéalement en répertoriant uniquement les colonnes de la table INFORMATION_SCHEMA que vous souhaitez, au lieu d'utiliser *select ** comme je le fais ici) :

select * from INFORMATION_SCHEMA.COLUMNS where TABLE_NAME = 'ABC'

Vous surveillerez différentes colonnes et vues INFORMATION_SCHEMA en fonction de la manière exacte dont vous définissez les « modifications apportées à une table ».

Devinette sauvage ici :Si vous ne souhaitez pas modifier les tables du tiers, pouvez-vous créer une vue puis mettre un déclencheur sur cette vue ?

Vérifiez la date du dernier commit.Chaque base de données a un historique du moment où chaque validation est effectuée.Je crois que c'est une norme de conformité ACID.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top