Capture de l'heure de modification dans CDC SQL Server

8

Nous avons donc commencé à explorer l'utilisation de la capture de données modifiées sur l'une de nos bases de données de production. Nous aimerions connaître l'heure de chaque modification. En lisant les procédures pas à pas et les didacticiels, etc., il semble que l'approche standard consiste à utiliser le LSN pour se rapporter à la cdc.lsn_time_mappingtable système. Cette approche fonctionne mais n'est pas très simple ni performante lorsqu'on parle de centaines de milliers de changements par jour.

Dans un environnement de test, j'ai apporté les ajustements suivants aux tables de suivi des modifications. J'ai émis une ALTER TABLEdéclaration pour ajouter une colonne à la fin appelée [__ChangeDateTime]et j'ai fait sa valeur par défaut GetDate(). L'approche semble fonctionner, le suivi des modifications fonctionne toujours normalement, les datetime sont capturés. Mais fouiner avec les tables système me rend un peu nerveux.

Si ce n'est pas un champ système que Microsoft a ajouté depuis le début, ils doivent avoir leurs raisons. Puisqu'ils ont plutôt opté pour l'approche LSN to cdc.lsn_time_mapping, est-ce que je me prépare à des problèmes en créant mon propre hack de cette façon?

MISE À JOUR:

Nous avons découvert lors des tests que GetDate () n'est parfois pas assez précis pour nos besoins - plusieurs changements partageant la même heure. Recommandez d'utiliser sysdatetime () et datetime2 pour déplacer la valeur à la nanoseconde. Option pour 2008+ seulement évidemment.

RThomas
la source

Réponses:

8

N'oubliez pas que CDC utilise un agent de lecteur de journaux pour remplir la table de modifications. Pourquoi est-ce important? Par ce mécanisme, les lignes s'affichent dans les tables de modifications de manière asynchrone aux modifications apportées dans les tables de base.

Il y a en fait 3 points de temps différents qui peuvent être enregistrés, dans l'ordre chronologique inverse:

  1. Heure à laquelle la modification a été envoyée à la table de modification (qui correspond à ce que vous enregistrez).
  2. Heure à laquelle la transaction contenant la modification a été validée (en utilisant cdc.lsn_time_mapping).
  3. Heure à laquelle vous remplissez manuellement une colonne dans la table de base (à l'aide d'une contrainte par défaut, d'un déclencheur, etc.).

Donc, la première chose est d'être clair sur ce que vous voulez enregistrer. Habituellement, nous nous soucions du # 2 ou du # 3.

Si le mécanisme de mappage LSN (# 2) ne fonctionne pas assez bien pour vous, la seule alternative prise en charge consiste à ajouter une colonne à la table de base et à la remplir vous-même (# 3).

En ce qui concerne la modification des tables internes, par principe, je pense qu'il est préférable d'éviter de pirater avec des internes lorsqu'il existe des alternatives prises en charge. La dernière chose que vous voulez, c'est un système de production important qui tombe en panne, qui doit appeler le support produit et se voir refuser le service en raison de quelque chose comme ça. Peu importe les problèmes de rupture potentielle (mises à niveau) ou de rupture parce que c'était inattendu (désactivez CDC, puis rallumez-le, comme mentionné dans l'autre réponse).

Jon Seigel
la source
3

Un exemple pratique:

USE Database;
GO

DECLARE @from_lsn binary(10), @to_lsn binary(10)
SET @from_lsn = sys.fn_cdc_get_min_lsn('schema_tablename')
SET @to_lsn = sys.fn_cdc_get_max_lsn()

SELECT
    sys.fn_cdc_map_lsn_to_time(__$start_lsn) AS 'Time'
    ,[Field1]
    ,[Field2]
    ,[Field3]
FROM [cdc].[fn_cdc_get_all_changes_schema_tablename]
  (@from_lsn, @to_lsn, N'all');
Gareth Orrill
la source
Cette réponse bénéficierait de quelques commentaires expliquant ce que vous faites et pourquoi elle est pertinente.
Erik
2

La seule mise en garde que je donnerais est que ces tables sont supprimées automatiquement lorsque CDC est désactivé. La colonne ne sera pas recréée automatiquement lorsque vous la renaturerez

Liam Confrey
la source