Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Anwendungen, die die Änderungsnachverfolgung verwenden, müssen nachverfolgte Änderungen abrufen, diese Änderungen auf einen anderen Datenspeicher anwenden und die Quelldatenbank aktualisieren können. In diesem Thema wird beschrieben, wie diese Aufgaben ausgeführt werden, und welche Rolle die Änderungsnachverfolgung spielt, wenn ein Failover auftritt und eine Datenbank aus einer Sicherung wiederhergestellt werden muss.
Änderungen mithilfe der Änderungsnachverfolgungsfunktionen abrufen
Beschreibt, wie Die Änderungsnachverfolgungsfunktionen verwendet werden, um Änderungen und Informationen zu den Änderungen abzurufen, die an einer Datenbank vorgenommen wurden.
Informationen zu den Funktionen zur Änderungsnachverfolgung
Anwendungen können mit den folgenden Funktionen die in einer Datenbank vorgenommenen Änderungen sowie die Informationen zu diesen Änderungen abrufen:
CHANGETABLE(CHANGES ...)
Diese Rowset-Funktion wird verwendet, um Änderungsinformationen abzufragen. Die Funktion fragt die in den internen Änderungsnachverfolgungstabellen gespeicherten Daten ab. Die Funktion gibt einen Resultset zurück, der die Primärschlüssel von Zeilen enthält, die zusammen mit anderen Änderungsinformationen wie dem Vorgang, den aktualisierten Spalten und der Version für die Zeile geändert wurden.
CHANGETABLE(CHANGES ...) verwendet eine letzte Synchronisierungsversion als Argument. Die letzte Sychronisierungsversion wird mithilfe der @last_synchronization_version Variablen abgerufen. Die Semantik der letzten Synchronisierungsversion lautet wie folgt:
Der aufrufende Client hat Änderungen erhalten und kennt alle Änderungen bis einschließlich der letzten Synchronisierungsversion.
CHANGETABLE(CHANGES ...) gibt daher alle Änderungen zurück, die nach der letzten Synchronisierungsversion aufgetreten sind.
Die folgende Abbildung zeigt, wie CHANGETABLE(CHANGES ...) verwendet wird, um Änderungen zu erhalten.
„CHANGE_TRACKING_CURRENT_VERSION()“-Funktion
Wird verwendet, um die aktuelle Version abzurufen, die beim nächsten Abfragen von Änderungen verwendet wird. Diese Version stellt die Version der letzten Transaktion dar, für die ein Commit ausgeführt wurde.
CHANGE_TRACKING_MIN_VALID_VERSION()-Funktion
Wird verwendet, um die mindestens gültige Version abzurufen, die ein Client haben kann und dennoch gültige Ergebnisse von CHANGETABLE() abrufen kann. Der Client sollte die letzte Synchronisierungsversion anhand des Werts überprüfen, der von dieser Funktion zurückgegeben wird. Wenn die letzte Synchronisierungsversion kleiner als die von dieser Funktion zurückgegebene Version ist, kann der Client keine gültigen Ergebnisse von CHANGETABLE() abrufen und muss erneut initialisiert werden.
Abrufen von Anfangsdaten
Bevor eine Anwendung zum ersten Mal Änderungen erhalten kann, muss die Anwendung eine Abfrage senden, um die anfänglichen Daten und die Synchronisierungsversion abzurufen. Die Anwendung muss die entsprechenden Daten direkt aus der Tabelle abrufen und dann CHANGE_TRACKING_CURRENT_VERSION() verwenden, um die ursprüngliche Version abzurufen. Diese Version wird an CHANGETABLE(CHANGES ...) übergeben, wenn änderungen zum ersten Mal abgerufen werden.
Das folgende Beispiel zeigt, wie Sie die ursprüngliche Synchronisierungsversion und den anfänglichen Datensatz abrufen.
-- Obtain the current synchronization version. This will be used next time that changes are obtained.
SET @synchronization_version = CHANGE_TRACKING_CURRENT_VERSION();
-- Obtain initial data set.
SELECT
P.ProductID, P.Name, P.ListPrice
FROM
SalesLT.Product AS P
Verwenden der Änderungsnachverfolgungsfunktionen zum Abrufen von Änderungen
Verwenden Sie CHANGETABLE(CHANGES...), um die geänderten Zeilen für eine Tabelle und Informationen zu den Änderungen abzurufen. Die folgende Abfrage ruft beispielsweise Änderungen für die SalesLT.Product Tabelle ab.
SELECT
CT.ProductID, CT.SYS_CHANGE_OPERATION,
CT.SYS_CHANGE_COLUMNS, CT.SYS_CHANGE_CONTEXT
FROM
CHANGETABLE(CHANGES SalesLT.Product, @last_synchronization_version) AS CT
In der Regel möchte ein Client die neuesten Daten für eine Zeile anstelle der Primärschlüssel für die Zeile abrufen. Daher würde eine Anwendung die Ergebnisse aus CHANGETABLE(CHANGES ...) mit den Daten in der Benutzertabelle verknüpfen. Beispiel: Bei der folgenden Abfrage wird die Funktion mit der SalesLT.Product -Tabelle verknüpft, um die Werte der Name -Spalte und der ListPrice -Spalte abzurufen. Beachten Sie, dass OUTER JOINverwendet wird. Dies ist erforderlich, um sicherzustellen, dass die Änderungsinformationen für die Zeilen zurückgegeben werden, die aus der Benutzertabelle gelöscht wurden.
SELECT
CT.ProductID, P.Name, P.ListPrice,
CT.SYS_CHANGE_OPERATION, CT.SYS_CHANGE_COLUMNS,
CT.SYS_CHANGE_CONTEXT
FROM
SalesLT.Product AS P
RIGHT OUTER JOIN
CHANGETABLE(CHANGES SalesLT.Product, @last_synchronization_version) AS CT
ON
P.ProductID = CT.ProductID
Um die Version für die Verwendung in der nächsten Änderungsenumeration zu erhalten, verwenden Sie CHANGE_TRACKING_CURRENT_VERSION(), wie im folgenden Beispiel gezeigt.
SET @synchronization_version = CHANGE_TRACKING_CURRENT_VERSION()
Wenn eine Anwendung Änderungen abruft, muss sie sowohl CHANGETABLE(CHANGES...) als auch CHANGE_TRACKING_CURRENT_VERSION() verwenden, wie im folgenden Beispiel gezeigt.
-- Obtain the current synchronization version. This will be used the next time CHANGETABLE(CHANGES...) is called.
SET @synchronization_version = CHANGE_TRACKING_CURRENT_VERSION();
-- Obtain incremental changes by using the synchronization version obtained the last time the data was synchronized.
SELECT
CT.ProductID, P.Name, P.ListPrice,
CT.SYS_CHANGE_OPERATION, CT.SYS_CHANGE_COLUMNS,
CT.SYS_CHANGE_CONTEXT
FROM
SalesLT.Product AS P
RIGHT OUTER JOIN
CHANGETABLE(CHANGES SalesLT.Product, @last_synchronization_version) AS CT
ON
P.ProductID = CT.ProductID
Versionsnummern
Eine Datenbank mit aktivierter Änderungsnachverfolgung besitzt einen Versionszähler, der zunimmt, sobald Änderungen an änderungsnachverfolgten Tabellen vorgenommen werden. Jede geänderte Zeile weist eine Versionsnummer auf, die ihr zugeordnet ist. Wenn eine Anforderung an eine Anwendung gesendet wird, um Änderungen abzufragen, wird eine Funktion aufgerufen, die eine Versionsnummer bereitstellt. Die Funktion gibt Informationen zu allen Änderungen zurück, die seit dieser Version vorgenommen wurden. In einigen Fällen ähnelt die Änderungsverfolgungsversion dem rowversion Datentyp.
Überprüfen der letzten synchronisierten Version
Informationen zu Änderungen werden für einen begrenzten Zeitraum beibehalten. Die Zeitdauer wird durch den parameter CHANGE_RETENTION gesteuert, der als Teil der ALTER DATABASE angegeben werden kann.
Beachten Sie, dass die für CHANGE_RETENTION angegebene Zeit bestimmt, wie häufig alle Anwendungen Änderungen aus der Datenbank anfordern müssen. Wenn eine Anwendung einen Wert für last_synchronization_version hat, der älter als die mindestens gültige Synchronisierungsversion für eine Tabelle ist, kann diese Anwendung keine gültige Änderungsenumeration ausführen. Dies liegt daran, dass einige Änderungsinformationen möglicherweise bereinigt wurden. Bevor eine Anwendung Änderungen mithilfe von CHANGETABLE(CHANGES ...) abruft, muss die Anwendung den Wert für last_synchronization_version überprüfen, den sie an CHANGETABLE(CHANGES ...)übergeben soll. Wenn der Wert von last_synchronization_version ungültig ist, muss diese Anwendung alle Daten neu initialisieren.
Das folgende Beispiel zeigt, wie die Gültigkeit des Werts last_synchronization_version für jede Tabelle überprüft wird.
-- Check individual table.
IF (@last_synchronization_version < CHANGE_TRACKING_MIN_VALID_VERSION(
OBJECT_ID('SalesLT.Product')))
BEGIN
-- Handle invalid version and do not enumerate changes.
-- Client must be reinitialized.
END
Wie im folgenden Beispiel gezeigt, kann die Gültigkeit des Werts last_synchronization_version für alle Tabellen in der Datenbank überprüft werden.
-- Check all tables with change tracking enabled
IF EXISTS (
SELECT COUNT(*) FROM sys.change_tracking_tables
WHERE min_valid_version > @last_synchronization_version )
BEGIN
-- Handle invalid version & do not enumerate changes
-- Client must be reinitialized
END
Verwenden der Spaltennachverfolgung
Die Spaltennachverfolgung ermöglicht Anwendungen das Abrufen der Daten nur für die Spalten, die sich anstelle der gesamten Zeile geändert haben. Betrachten Sie beispielsweise das Szenario, in dem eine Tabelle eine oder mehrere Spalten enthält, die groß sind, aber selten geändert werden; und hat auch andere Spalten, die sich häufig ändern. Ohne Spaltennachverfolgung kann eine Anwendung nur bestimmen, dass sich eine Zeile geändert hat und alle Daten synchronisieren muss, die die großen Spaltendaten enthalten. Mithilfe der Spaltennachverfolgung kann eine Anwendung jedoch bestimmen, ob sich die großen Spaltendaten geändert haben, und nur die Daten synchronisieren, wenn sie geändert wurden.
Spaltenverfolgungsinformationen werden in der spalte SYS_CHANGE_COLUMNS angezeigt, die von der Funktion CHANGETABLE(CHANGES ...) zurückgegeben wird.
Die Spaltennachverfolgung kann verwendet werden, sodass NULL für eine Spalte zurückgegeben wird, die sich nicht geändert hat. Wenn die Spalte in NULL geändert werden kann, muss eine separate Spalte zurückgegeben werden, um anzugeben, ob die Spalte geändert wurde.
Im folgenden Beispiel wird die CT_ThumbnailPhoto Spalte NULL, wenn sich die Spalte nicht geändert hat. Diese Spalte könnte auch NULL sein, weil sie zu NULL geändert wurde – die Anwendung kann die CT_ThumbNailPhoto_Changed Spalte nutzen, um zu bestimmen, ob die Spalte geändert wurde.
DECLARE @PhotoColumnId int = COLUMNPROPERTY(
OBJECT_ID('SalesLT.Product'),'ThumbNailPhoto', 'ColumnId')
SELECT
CT.ProductID, P.Name, P.ListPrice, -- Always obtain values.
CASE
WHEN CHANGE_TRACKING_IS_COLUMN_IN_MASK(
@PhotoColumnId, CT.SYS_CHANGE_COLUMNS) = 1
THEN ThumbNailPhoto
ELSE NULL
END AS CT_ThumbNailPhoto,
CHANGE_TRACKING_IS_COLUMN_IN_MASK(
@PhotoColumnId, CT.SYS_CHANGE_COLUMNS) AS
CT_ThumbNailPhoto_Changed
CT.SYS_CHANGE_OPERATION, CT.SYS_CHANGE_COLUMNS,
CT.SYS_CHANGE_CONTEXT
FROM
SalesLT.Product AS P
INNER JOIN
CHANGETABLE(CHANGES SalesLT.Product, @last_synchronization_version) AS CT
ON
P.ProductID = CT.ProductID AND
CT.SYS_CHANGE_OPERATION = 'U'
Abrufen konsistenter und korrekter Ergebnisse
Das Abrufen der geänderten Daten für eine Tabelle erfordert mehrere Schritte. Beachten Sie, dass inkonsistente oder falsche Ergebnisse zurückgegeben werden können, wenn bestimmte Probleme nicht berücksichtigt und behandelt werden.
Um beispielsweise die Änderungen abzurufen, die an einer Tabelle "Sales" und "SalesOrders" vorgenommen wurden, führt eine Anwendung die folgenden Schritte aus:
Validieren Sie die letzte synchronisierte Version mithilfe von CHANGE_TRACKING_MIN_VALID_VERSION().
Rufen Sie die Version ab, die das nächste Mal mithilfe von CHANGE_TRACKING_CURRENT_VERSION() zur Änderung verwendet werden kann.
Verwenden Sie CHANGETABLE(CHANGES ...) um die Änderungen der „Sales“-Tabelle abzurufen.
Rufen Sie die Änderungen für die Tabelle "SalesOrders" mithilfe von CHANGETABLE(CHANGES ...) ab.
In der Datenbank treten zwei Prozesse auf, die sich auf die Ergebnisse auswirken können, die von den vorherigen Schritten zurückgegeben werden:
Der Bereinigungsprozess wird im Hintergrund ausgeführt und entfernt Änderungsnachverfolgungsinformationen, die älter als der angegebene Aufbewahrungszeitraum sind.
Der Bereinigungsprozess ist ein separater Hintergrundprozess, der den Aufbewahrungszeitraum verwendet, der angegeben wird, wenn Sie die Änderungsnachverfolgung für die Datenbank konfigurieren. Das Problem besteht darin, dass der Bereinigungsprozess zwischen dem Zeitpunkt der Überprüfung der letzten Synchronisierungsversion und dem Zeitpunkt, zu dem der Aufruf von CHANGETABLE(CHANGES...) durchgeführt wird, auftreten kann. Eine zuletzt gültige Synchronisierungsversion ist möglicherweise nicht mehr gültig, wenn die Änderungen abgerufen werden. Daher werden möglicherweise falsche Ergebnisse zurückgegeben.
Laufende DML-Vorgänge treten in den Tabellen "Sales" und "SalesOrders" auf, z. B. in den folgenden Vorgängen:
Änderungen können an den Tabellen vorgenommen werden, nachdem die Version zum nächsten Mal mithilfe von CHANGE_TRACKING_CURRENT_VERSION() abgerufen wurde. Daher können mehr Änderungen zurückgegeben werden als erwartet.
Eine Transaktion könnte in der Zeit zwischen dem Abrufen von Änderungen aus der Tabelle "Sales" und dem Abrufen von Änderungen aus der Tabelle "SalesOrders" abgeschlossen werden. Daher könnten die Ergebnisse für die Tabelle "SalesOrder" einen Fremdschlüsselwert aufweisen, der in der Tabelle "Sales" nicht vorhanden ist.
Um die zuvor aufgeführten Herausforderungen zu überwinden, empfiehlt es sich, die Snapshotisolation zu verwenden. Dies trägt dazu bei, die Konsistenz von Änderungsinformationen sicherzustellen und Rennbedingungen zu vermeiden, die mit der Hintergrundbereinigungsaufgabe zusammenhängen. Wenn Sie keine Snapshot-Transaktionen verwenden, kann die Entwicklung einer Anwendung, die die Änderungsnachverfolgung verwendet, erheblich mehr Aufwand erfordern.
Verwenden der Snapshot Isolation
Die Änderungsnachverfolgung wurde so konzipiert, dass sie gut mit der Snapshotisolation funktioniert. Die Momentaufnahmeisolation muss für die Datenbank aktiviert sein. Alle Schritte, die zum Abrufen von Änderungen erforderlich sind, müssen in einer Momentaufnahmetransaktion enthalten sein. Dadurch wird sichergestellt, dass alle Änderungen, die an Daten vorgenommen werden, beim Abrufen von Änderungen für die Abfragen innerhalb der Momentaufnahmetransaktion nicht sichtbar sind.
Führen Sie die folgenden Schritte aus, um Daten innerhalb einer Momentaufnahmetransaktion abzurufen:
Legen Sie die Transaktionsisolationsstufe auf Momentaufnahme fest, und starten Sie eine Transaktion.
Überprüfen Sie die letzte Synchronisierungsversion mithilfe von CHANGE_TRACKING_MIN_VALID_VERSION().
Rufen Sie die Version ab, die beim nächsten Mal verwendet werden soll, indem Sie CHANGE_TRACKING_CURRENT_VERSION() verwenden.
Abrufen der Änderungen für die Tabelle "Vertrieb" mithilfe von CHANGETABLE(CHANGES ...)
Veränderungen für die Tabelle "Bestellungen" durch Verwendung von CHANGETABLE(CHANGES ...) abrufen.
Transaktion abschließen.
Einige Punkte, die sie beachten sollten, da sich alle Schritte zum Abrufen von Änderungen in einer Momentaufnahmetransaktion befinden:
Wenn die Bereinigung erfolgt, nachdem die letzte Synchronisierungsversion überprüft wurde, sind die Ergebnisse aus CHANGETABLE(CHANGES ...) weiterhin gültig, da die von der Bereinigung ausgeführten Löschvorgänge nicht innerhalb der Transaktion sichtbar sind.
Alle Änderungen, die an der Tabelle "Sales" oder der Tabelle "SalesOrders" vorgenommen werden, nachdem die nächste Synchronisierungsversion abgerufen wurde, sind nicht sichtbar, und die Aufrufe von CHANGETABLE(CHANGES ...) geben niemals Änderungen mit einer späteren Version zurück, als die von CHANGE_TRACKING_CURRENT_VERSION() zurückgegeben wurde. Die Konsistenz zwischen der Tabelle "Sales" und der Tabelle "SalesOrders" wird ebenfalls beibehalten, da die Transaktionen, die im Zeitraum zwischen Aufrufen von CHANGETABLE(CHANGES ...) zugesichert wurden, nicht sichtbar sind.
Das folgende Beispiel zeigt, wie die Snapshotisolation für eine Datenbank aktiviert ist.
-- The database must be configured to enable snapshot isolation.
ALTER DATABASE AdventureWorksLT
SET ALLOW_SNAPSHOT_ISOLATION ON;
Eine Momentaufnahmetransaktion wird wie folgt verwendet:
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
BEGIN TRAN
-- Verify that version of the previous synchronization is valid.
-- Obtain the version to use next time.
-- Obtain changes.
COMMIT TRAN
Weitere Informationen zu Snapshot-Transaktionen finden Sie unter SET TRANSACTION ISOLATION LEVEL (Transact-SQL).
Alternativen zur Nutzung der Snapshotisolation
Es gibt Alternativen zur Verwendung der Snapshotisolation, aber sie erfordern mehr Arbeit, um sicherzustellen, dass alle Anwendungsanforderungen erfüllt sind. Gehen Sie wie folgt vor, um sicherzustellen, dass der last_synchronization_version gültig ist und die Daten nicht vom Bereinigungsprozess entfernt werden, bevor Änderungen abgerufen werden:
Überprüfen Sie last_synchronization_version nach den Aufrufen von CHANGETABLE().
Überprüfen Sie last_synchronization_version als Teil jeder Abfrage, um Änderungen mithilfe von CHANGETABLE() zu erhalten.
Änderungen können auftreten, nachdem die Synchronisierungsversion für die nächste Enumeration abgerufen wurde. Es gibt zwei Möglichkeiten, diese Situation zu bewältigen. Die verwendete Option hängt von der Anwendung ab und wie sie die Nebenwirkungen der einzelnen Ansätze behandeln kann:
Ignorieren Sie Änderungen, die eine Version haben, die größer als die neue Synchronisierungsversion ist.
Dieser Ansatz hat den Nebeneffekt, dass eine neue oder aktualisierte Zeile übersprungen wird, wenn sie vor der neuen Synchronisierungsversion erstellt oder aktualisiert wurde und danach wiederum eine Aktualisierung erfährt. Wenn eine neue Zeile vorhanden ist, kann ein Problem mit der referenziellen Integrität auftreten, wenn eine Zeile in einer anderen Tabelle vorhanden war, die erstellt wurde, die auf die übersprungene Zeile verweist. Wenn eine aktualisierte Zeile vorhanden ist, wird die Zeile übersprungen und nicht synchronisiert bis zum nächsten Mal.
Schließen Sie alle Änderungen ein, auch diejenigen, die eine Version haben, die größer als die neue Synchronisierungsversion ist.
Die Zeilen mit einer Version, die größer als die neue Synchronisierungsversion ist, werden bei der nächsten Synchronisierung erneut abgerufen. Dies muss von der Anwendung erwartet und behandelt werden.
Zusätzlich zu den beiden vorherigen Optionen können Sie einen Ansatz entwickeln, der beide Optionen kombiniert, je nach Vorgang. Sie möchten beispielsweise, dass eine Anwendung, für die Änderungen am besten ignoriert werden sollten, die neuer sind als die nächste Synchronisierungsversion, in der die Zeile erstellt oder gelöscht wurde, bei Aktualisierungen jedoch nicht ignoriert werden.
Hinweis
Wenn Sie den Ansatz auswählen, der für die Anwendung funktioniert, wenn Sie die Änderungsnachverfolgung (oder einen benutzerdefinierten Nachverfolgungsmechanismus) verwenden, ist eine erhebliche Analyse erforderlich. Daher ist es viel einfacher, Snapshotisolation zu verwenden.
So behandelt die Änderungsnachverfolgung Änderungen an einer Datenbank
Einige Anwendungen, die die Änderungsnachverfolgung verwenden, führen eine bidirektionale Synchronisierung mit einem anderen Datenspeicher durch. Das heißt, Änderungen, die in der SQL Server-Datenbank vorgenommen werden, werden im anderen Datenspeicher aktualisiert, und Änderungen, die im anderen Speicher vorgenommen werden, werden in der SQL Server-Datenbank aktualisiert.
Wenn eine Anwendung die lokale Datenbank mit Änderungen aus einem anderen Datenspeicher aktualisiert, muss die Anwendung die folgenden Vorgänge ausführen:
Prüfen Sie, ob Konflikte vorliegen.
Ein Konflikt tritt auf, wenn die gleichen Daten gleichzeitig in beiden Datenspeichern geändert werden. Die Anwendung muss in der Lage sein, nach einem Konflikt zu suchen und genügend Informationen zu erhalten, damit der Konflikt gelöst werden kann.
Speichern von Anwendungskontextinformationen.
Die Anwendung speichert Daten, die über die Informationen zur Änderungsnachverfolgung verfügen. Diese Informationen wären zusammen mit anderen Änderungsverfolgungsinformationen verfügbar, wenn Änderungen aus der lokalen Datenbank abgerufen wurden. Ein gängiges Beispiel für diese Kontextinformationen ist ein Bezeichner für den Datenspeicher, der die Quelle der Änderung war.
Zum Ausführen der vorherigen Vorgänge kann eine Synchronisierungsanwendung die folgenden Funktionen verwenden:
CHANGETABLE(VERSION...)
Wenn eine Anwendung Änderungen vornimmt, kann sie diese Funktion verwenden, um nach Konflikten zu suchen. Die Funktion ruft die neuesten Änderungsverfolgungsinformationen für eine angegebene Zeile in einer nachverfolgten Tabelle ab. Die Änderungsnachverfolgungsinformationen enthalten die Version der Zeile, die zuletzt geändert wurde. Mit diesen Informationen kann eine Anwendung ermitteln, ob die Zeile nach der letzten Synchronisierung der Anwendung geändert wurde.
WITH CHANGE_TRACKING_CONTEXT
Eine Anwendung kann diese Klausel verwenden, um Kontextdaten zu speichern.
Überprüfen auf Konflikte
In einem bidirektionales Synchronisierungsszenario muss die Clientanwendung bestimmen, ob eine Zeile seit dem letzten Erhalten der Änderungen nicht aktualisiert wurde.
Im folgenden Beispiel wird gezeigt, wie die FUNKTION CHANGETABLE(VERSION ...) verwendet wird, um konflikte effizient und ohne separate Abfrage zu überprüfen. Im Beispiel bestimmt CHANGETABLE(VERSION ...) den SYS_CHANGE_VERSION für die durch @product id angegebene Zeile.
CHANGETABLE(CHANGES ...) kann dieselben Informationen erhalten, aber das wäre weniger effizient. Wenn der Wert SYS_CHANGE_VERSION der Zeile größer als der Wert der @last_sync_versionZeile ist, liegt ein Konflikt vor. Wenn ein Konflikt vorliegt, wird die Zeile nicht aktualisiert. Die ISNULL() Überprüfung ist erforderlich, da möglicherweise keine Änderungsinformationen für die Zeile verfügbar sind. Es wären keine Änderungsinformationen vorhanden, wenn die Zeile seit der Aktivierung der Änderungsnachverfolgung nicht aktualisiert wurde oder die Änderungsinformationen bereinigt wurden.
-- Assumption: @last_sync_version has been validated.
UPDATE
SalesLT.Product
SET
ListPrice = @new_listprice
FROM
SalesLT.Product AS P
WHERE
ProductID = @product_id AND
@last_sync_version >= ISNULL (
SELECT CT.SYS_CHANGE_VERSION
FROM CHANGETABLE(VERSION SalesLT.Product,
(ProductID), (P.ProductID)) AS CT),
0)
Der folgende Code kann die aktualisierte Zeilenanzahl überprüfen und weitere Informationen zum Konflikt identifizieren.
-- If the change cannot be made, find out more information.
IF (@@ROWCOUNT = 0)
BEGIN
-- Obtain the complete change information for the row.
SELECT
CT.SYS_CHANGE_VERSION, CT.SYS_CHANGE_CREATION_VERSION,
CT.SYS_CHANGE_OPERATION, CT.SYS_CHANGE_COLUMNS
FROM
CHANGETABLE(CHANGES SalesLT.Product, @last_sync_version) AS CT
WHERE
CT.ProductID = @product_id;
-- Check CT.SYS_CHANGE_VERSION to verify that it really was a conflict.
-- Check CT.SYS_CHANGE_OPERATION to determine the type of conflict:
-- update-update or update-delete.
-- The row that is specified by @product_id might no longer exist
-- if it has been deleted.
END
Festlegen von Kontextinformationen
Mithilfe der WITH CHANGE_TRACKING_CONTEXT-Klausel kann eine Anwendung Kontextinformationen zusammen mit den Änderungsinformationen speichern. Diese Informationen können dann aus der spalte SYS_CHANGE_CONTEXT abgerufen werden, die von CHANGETABLE(CHANGES ...)zurückgegeben wird.
Kontextinformationen werden in der Regel verwendet, um die Quelle der Änderungen zu identifizieren. Wenn die Quelle der Änderung identifiziert werden kann, können diese Informationen von einem Datenspeicher verwendet werden, um das Abrufen von Änderungen zu vermeiden, wenn sie erneut synchronisiert wird.
-- Try to update the row and check for a conflict.
WITH CHANGE_TRACKING_CONTEXT (@source_id)
UPDATE
SalesLT.Product
SET
ListPrice = @new_listprice
FROM
SalesLT.Product AS P
WHERE
ProductID = @product_id AND
@last_sync_version >= ISNULL (
(SELECT CT.SYS_CHANGE_VERSION FROM CHANGETABLE(VERSION SalesLT.Product,
(ProductID), (P.ProductID)) AS CT),
0)
Sicherstellen konsistenter und korrekter Ergebnisse
Eine Anwendung muss den Bereinigungsprozess berücksichtigen, wenn sie den Wert von @last_sync_version validiert. Dies liegt daran, dass Daten nach dem Aufruf CHANGE_TRACKING_MIN_VALID_VERSION() entfernt werden konnten, aber bevor die Aktualisierung vorgenommen wurde.
Von Bedeutung
Es wird empfohlen, die Snapshot-Isolation zu verwenden und die Änderungen im Rahmen einer Momentaufnahmetransaktion vorzunehmen.
-- Prerequisite is to ensure ALLOW_SNAPSHOT_ISOLATION is ON for the database.
SET TRANSACTION ISOLATION LEVEL SNAPSHOT;
BEGIN TRAN
-- Verify that last_sync_version is valid.
IF (@last_sync_version <
CHANGE_TRACKING_MIN_VALID_VERSION(OBJECT_ID('SalesLT.Product')))
BEGIN
RAISERROR (N'Last_sync_version too old', 16, -1);
END
ELSE
BEGIN
-- Try to update the row.
-- Check @@ROWCOUNT and check for a conflict.
END
COMMIT TRAN
Hinweis
Es besteht die Möglichkeit, dass die Zeile, die innerhalb der Momentaufnahmetransaktion aktualisiert wird, in einer anderen Transaktion aktualisiert worden sein könnte, nachdem die Momentaufnahmetransaktion gestartet wurde. In diesem Fall tritt ein Momentaufnahme-Isolationskonflikt auf und führt dazu, dass die Transaktion beendet wird. Wenn dies der Fall ist, wiederholen Sie das Update. Dies führt dann dazu, dass ein Änderungsnachverfolgungskonflikt erkannt wird und keine Zeilen geändert werden.
Änderungsnachverfolgung und Datenwiederherstellung
Anwendungen, die eine Synchronisierung erfordern, müssen den Fall berücksichtigen, in dem eine Datenbank mit aktivierter Änderungsnachverfolgung auf eine frühere Version der Daten zurückgesetzt wird. Dies kann auftreten, nachdem eine Datenbank aus einer Sicherung wiederhergestellt wurde, bei einem Failover zu einem asynchronen Datenbankspiegel oder bei einem Fehler im Protokollversand. Das folgende Szenario veranschaulicht das Problem:
Tabelle T1 ist mit Änderungsverfolgung versehen, und die mindestens gültige Version für die Tabelle ist 50.
Eine Clientanwendung synchronisiert Daten mit Version 100 und ruft Informationen zu allen Änderungen zwischen Den Versionen 50 und 100 ab.
Nach Version 100 werden weitere Änderungen an Tabelle T1 vorgenommen.
In Version 120 ist ein Fehler aufgetreten, und der Datenbankadministrator stellt die Datenbank mit Datenverlust wieder her. Nach dem Wiederherstellungsvorgang enthält die Tabelle Daten bis Version 70, und die mindestens synchronisierte Version ist noch 50.
Dies bedeutet, dass der synchronisierte Datenspeicher Daten enthält, die nicht mehr im primären Datenspeicher vorhanden sind.
T1 wird mehrmals aktualisiert. Dies bringt die aktuelle Version auf 130.
Die Clientanwendung wird erneut synchronisiert und stellt eine zuletzt synchronisierte Version von 100 zur Auswahl. Der Client überprüft diese Nummer erfolgreich, da 100 größer als 50 ist.
Der Client ruft Änderungen zwischen Version 100 und 130 ab. An diesem Punkt ist dem Client nicht bekannt, dass die Änderungen zwischen 70 und 100 nicht identisch sind wie zuvor. Die Daten auf dem Client und server werden nicht synchronisiert.
Beachten Sie, dass es keine Probleme mit der Synchronisierung gibt, wenn die Datenbank nach Version 100 zu einem Punkt wiederhergestellt wurde. Der Client und der Server würden Daten während des nächsten Synchronisierungsintervalls ordnungsgemäß synchronisieren.
Die Änderungsnachverfolgung bietet keine Unterstützung für die Wiederherstellung aus dem Verlust von Daten. Es gibt jedoch zwei Optionen zum Erkennen dieser Arten von Synchronisierungsproblemen:
Speichern Sie eine Datenbankversions-ID auf dem Server, und aktualisieren Sie diesen Wert immer dann, wenn eine Datenbank wiederhergestellt wird oder anderweitig Daten verloren gehen. Jede Clientanwendung würde die ID speichern, und jeder Client muss diese ID überprüfen, wenn daten synchronisiert werden. Wenn Datenverlust auftritt, stimmen die IDs nicht überein, und die Clients werden erneut initialisiert. Ein Nachteil ist, wenn der Datenverlust die letzte synchronisierte Grenze nicht überschritten hatte, kann der Client unnötige Neuiniialisierung durchführen.
Wenn ein Client änderungen abfragt, notieren Sie die letzte Versionsnummer der Synchronisierung für jeden Client auf dem Server. Wenn ein Problem mit den Daten vorliegt, stimmen die zuletzt synchronisierten Versionsnummern nicht überein. Dies gibt an, dass eine Erneute Initialisierung erforderlich ist.
Siehe auch
Nachverfolgen von Datenänderungen (SQL Server)
Informationen zur Änderungsnachverfolgung (SQL Server)
Verwalten der Änderungsnachverfolgung (SQL Server)
Aktivieren und Deaktivieren der Änderungsnachverfolgung (SQL Server)
CHANGETABLE (Transact-SQL)
CHANGE_TRACKING_MIN_VALID_VERSION (Transact-SQL)
ÄNDERUNGSVERFOLGUNG_AKTUELLE_VERSION (Transact-SQL)
WITH CHANGE_TRACKING_CONTEXT (Transact-SQL)