Erfassen der Änderungszeit von Daten in SQL Server CDC

8

Daher haben wir begonnen, die Verwendung der Änderungsdatenerfassung in einer unserer Produktionsdatenbanken zu untersuchen. Wir möchten das Datum und die Uhrzeit jeder Änderung wissen. Beim Lesen von exemplarischen Vorgehensweisen, Tutorials usw. scheint es der Standardansatz zu sein, die LSN zu verwenden, um sich auf die Systemtabelle zu beziehen cdc.lsn_time_mapping. Dieser Ansatz funktioniert, ist jedoch weder sehr einfach noch performant, wenn über Hunderttausende von Änderungen pro Tag gesprochen wird.

In einer Testumgebung habe ich die folgenden Anpassungen an den Änderungsspurtabellen vorgenommen. Ich habe eine ALTER TABLEAnweisung ausgegeben , um dem aufgerufenen Ende eine Spalte hinzuzufügen, [__ChangeDateTime]und den Standardwert festgelegt GetDate(). Der Ansatz scheint zu funktionieren, die Änderungsverfolgung funktioniert immer noch normal, die Datums- und Uhrzeitangaben werden erfasst. Aber das Herumspielen mit Systemtischen macht mich etwas nervös.

Wenn dies kein Systemfeld ist, das Microsoft von Anfang an hinzugefügt hat , müssen sie ihre Gründe haben. Da sie sich stattdessen für den Ansatz von LSN zu cdc.lsn_time_mapping entschieden haben, richte ich mich auf Probleme ein, indem ich auf diese Weise meinen eigenen Hack erstelle?

AKTUALISIEREN:

Beim Testen wurde festgestellt, dass GetDate () manchmal nicht präzise genug für unsere Anforderungen ist - mehrere Änderungen werden gleichzeitig verwendet. Empfehlen Sie die Verwendung von sysdatetime () und datetime2 , um den Wert auf die Nanosekunde zu verschieben. Option für 2008+ nur offensichtlich.

RThomas
quelle

Antworten:

7

Denken Sie daran, dass CDC einen Protokollleser-Agenten verwendet, um die Änderungstabelle zu füllen. Warum ist das wichtig? Durch diesen Mechanismus werden Zeilen in den Änderungstabellen asynchron zu den in den Basistabellen vorgenommenen Änderungen angezeigt.

Es gibt tatsächlich 3 verschiedene Zeitpunkte, die in umgekehrter chronologischer Reihenfolge aufgezeichnet werden können:

  1. Die Zeit, zu der die Änderung an die Änderungstabelle übermittelt wurde (die Sie aufzeichnen).
  2. Die Zeit, zu der die Transaktion, die die Änderung enthielt, festgeschrieben wurde (mit cdc.lsn_time_mapping).
  3. Die Zeit, mit der Sie eine Spalte in der Basistabelle manuell füllen (unter Verwendung einer Standardeinschränkung, eines Auslösers usw.).

Als Erstes muss klar sein, was Sie aufnehmen möchten. Normalerweise kümmern wir uns entweder um # 2 oder # 3.

Wenn der LSN-Zuordnungsmechanismus (Nr. 2) für Sie nicht gut genug funktioniert, besteht die einzige unterstützte Alternative darin, der Basistabelle eine Spalte hinzuzufügen und diese selbst zu füllen (Nr. 3).

In Bezug auf das Ändern der internen Tabellen halte ich es aus politischen Gründen für am besten, das Hacken mit Interna zu vermeiden, wenn es unterstützte Alternativen gibt. Das allerletzte, was Sie wollen, ist ein wichtiges Produktionssystem, das ausfällt, den Produkt-Support anrufen muss und aus diesem Grund der Service verweigert wird. Es spielt keine Rolle, ob Probleme auftreten (Upgrades) oder weil sie unerwartet waren (CDC aus- und wieder einschalten, wie in der anderen Antwort erwähnt).

Jon Seigel
quelle
3

Ein praktisches Beispiel:

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
quelle
Diese Antwort würde von einigen Kommentaren profitieren, die erklären, was Sie tun und warum es relevant ist.
Erik
2

Die einzige Einschränkung, die ich geben würde, ist, dass diese Tabellen automatisch gelöscht werden, wenn CDC deaktiviert ist. Die Spalte wird beim erneuten Rendern nicht automatisch neu erstellt

Liam Confrey
quelle