Acquisizione del datetime di modifica nel CDC di SQL Server


8

Quindi abbiamo iniziato a esplorare utilizzando l'acquisizione dei dati di modifica su uno dei nostri database di produzione. Vorremmo conoscere il datetime di ogni modifica. Leggendo le procedure dettagliate, i tutorial, ecc., Sembra che l'approccio standard sia utilizzare l'LSN per fare riferimento alla cdc.lsn_time_mappingtabella di sistema. Questo approccio funziona ma non è molto semplice né efficace quando si parla di centinaia di migliaia di modifiche al giorno.

In un ambiente di test ho apportato le seguenti modifiche alle tabelle delle tracce di modifica. Ho rilasciato una ALTER TABLEdichiarazione per aggiungere una colonna alla fine chiamata [__ChangeDateTime]e ho reso il suo valore predefinito GetDate(). L'approccio sembra funzionare, il rilevamento delle modifiche funziona ancora normalmente, i datetime vengono acquisiti. Ma scherzare con i tavoli di sistema mi rende un po 'nervoso.

Se questo non è un campo di sistema che Microsoft ha aggiunto dall'inizio , devono averne avuto le ragioni. Dato che invece hanno optato per l'LSN per l'approccio cdc.lsn_time_mapping, mi sto preparando per i problemi creando il mio hack in questo modo?

AGGIORNARE:

Scoperto durante i test che GetDate () a volte non è abbastanza preciso per le nostre esigenze: più modifiche condividono contemporaneamente. Consiglia di usare sysdatetime () e datetime2 per spostare il valore al nanosecondo. Opzione per il 2008+ solo ovviamente.

Risposte:


8

Ricordare che CDC utilizza un agente di lettura log per popolare la tabella delle modifiche. Perché è importante? Con tale meccanismo, le righe vengono visualizzate in modo asincrono nelle tabelle delle modifiche alle modifiche apportate nelle tabelle di base.

In realtà ci sono 3 diversi punti temporali che possono essere registrati, in ordine cronologico inverso:

  1. L'ora in cui la modifica è stata consegnata alla tabella delle modifiche (che è ciò che stai registrando).
  2. L'ora in cui la transazione che conteneva la modifica è stata impegnata (usando cdc.lsn_time_mapping).
  3. Il tempo con cui si popola manualmente una colonna nella tabella di base (utilizzando un vincolo predefinito, un trigger, ecc.).

Quindi la prima cosa è essere chiari su ciò che si desidera registrare. Di solito ci preoccupiamo per il n. 2 o il n. 3.

Se il meccanismo di mappatura LSN (# 2) non funziona abbastanza bene per te, l'unica alternativa supportata è aggiungere una colonna alla tabella di base e popolarla tu stesso (# 3).

Per quanto riguarda la modifica delle tabelle interne, per motivi di politica, penso che sia meglio evitare di hackerare con gli interni quando ci sono alternative supportate. L'ultima cosa che desideri è un sistema di produzione importante che va in crash, ha bisogno di chiamare il supporto del prodotto e di essere negato il servizio a causa di qualcosa del genere. Non importa quali siano le cose che potrebbero rompersi (aggiornamenti) o essere rotti perché era inaspettato (spegni e riaccendi CDC, come menzionato nell'altra risposta).


3

Un esempio pratico:

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');

Questa risposta trarrebbe beneficio da alcuni commenti che spiegano cosa stai facendo e perché è pertinente.
Erik

2

L'unica avvertenza che vorrei dare è che quelle tabelle vengono eliminate automaticamente quando il CDC è disabilitato. La colonna non viene ricreata automaticamente quando la si rinnova

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.