Vérifier les modifications apportées à une table SQL Server?

Translate

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

J'aimerais pouvoir supporter n'importe quelSQL Server 2000SP4 ou plus récent. Mon application est une visualisation de données complémentaire pour le produit d'une autre entreprise. Notre base de clients se chiffre par milliers, je ne veux donc pas avoir à exiger que nous modifions la table du fournisseur tiers à chaque installation.

Par"modifications d'une table"Je veux dire des modifications des données de table, pas des modifications de la structure de la table.

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


Le meilleur plan d'action étant donné mes besoins (pas de déclencheurs ou de modification de schéma, SQL Server 2000 et 2005) semble être d'utiliser leBINARY_CHECKSUMfonction dansT-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 aux valeurs stockées.

This question and all comments follow the "Attribution Required."

Toutes les réponses

Translate

Jetez un œil à la commande CHECKSUM:

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

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

CHECKSUM

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)

La source
Translate

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

Il ne s'agit que 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 exemple les changements symétriques donnent le même CHECKSUM!

Par exemple. la solution avecCHECKSUM_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!

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

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

La source
Translate

Pourquoi ne voulez-vous pas utiliser de déclencheurs? Ils sont une bonne chose si vous les utilisez correctement. Si vous les utilisez comme un 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 pour la surveillance, ils ne sont pas vraiment considérés comme tabous.

La source
Translate

À 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 leCHECKSUM_AGG(BINARY_CHECKSUM(*))méthode suggérée par John, il analysera chaque ligne de la table spécifiée. leNOLOCKhint 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 que vous en disiez qu'une a changé.

Avez-vous envisagé de procéder 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'application qui crée la base de données?

Ils pourraient implémenter une API qui fournit un mécanisme pour notifier aux applications accessoires que les données ont changé. 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 mis en œuvre via des déclencheurs ou du code d'application. De votre côté, cela n'a pas d'importance, votre seule préoccupation serait de scanner régulièrement le tableau des notifications. L'atteinte des performances sur la base de données serait bien inférieure à l'analyse de chaque ligne pour les modifications.

Le plus dur serait de convaincre le fournisseur de l'application d'implémenter cette fonctionnalité. Étant donné que cela peut être géré entièrement via SQL via des déclencheurs, vous pouvez effectuer l'essentiel du travail pour eux 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, cela empêche la situation où l'ajout d'un déclencheur remplace par inadvertance un déclencheur fourni par le fournisseur.

La source
Translate

Malheureusement, je ne pense pas qu'il existe un moyen propre de faire cela dans SQL2000. Si vous limitez vos besoins à SQL Server 2005 (et versions ultérieures), vous êtes en affaires. Vous pouvez utiliser leSQLDependencyclasse dansSystem.Data.SqlClient. VoirNotifications de requête dans SQL Server (ADO.NET).

La source
Translate

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èmeINFORMATION_SCHEMAtables 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, vous savez que la structure a changé.

Exemple de requête pour renvoyer des informations concernant toutes les colonnes de la table ABC (idéalement ne listant que les colonnes de la table INFORMATION_SCHEMA que vous voulez, au lieu d'utiliser * select ** comme je le fais ici):

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

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

La source
Translate

Imaginez 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?

La source
ECE
Translate

Vérifiez la dernière date de validation. 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.

La source