Uwaga
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Dotyczy:SQL Server
Azure SQL Database
Azure SQL Managed Instance
Aplikacje korzystające ze śledzenia zmian muszą mieć możliwość uzyskiwania śledzonych zmian, stosowania tych zmian do innego magazynu danych i aktualizowania źródłowej bazy danych. W tym artykule opisano sposób wykonywania tych zadań, a także rolę, jaką odgrywa śledzenie zmian, gdy następuje przełączenie awaryjne i baza danych musi zostać przywrócona z kopii zapasowej.
Uzyskiwanie zmian przy użyciu funkcji śledzenia zmian
Opisuje sposób używania funkcji śledzenia zmian w celu uzyskania zmian i informacji o zmianach wprowadzonych w bazie danych.
Informacje o funkcjach śledzenia zmian
Aplikacje mogą używać następujących funkcji w celu uzyskania zmian wprowadzonych w bazie danych i informacji o zmianach:
funkcja CHANGETABLE(CHANGES ...)
Ta funkcja zestawu wierszy służy do wykonywania zapytań dotyczących informacji o zmianach. Funkcja wykonuje zapytania dotyczące danych przechowywanych w wewnętrznych tabelach śledzenia zmian. Funkcja zwraca zestaw wyników zawierający klucze podstawowe wierszy, które zostały zmienione razem z innymi informacjami o zmianie, takimi jak operacja, kolumny zaktualizowane i wersja wiersza.
FUNKCJA CHANGETABLE(CHANGES ...) przyjmuje ostatnią wersję synchronizacji jako argument. Ostatnia wersja synchronizacji jest uzyskiwana przy użyciu zmiennej @last_synchronization_version
. Semantyka ostatniej wersji synchronizacji jest następująca:
Klient wywołujący uzyskał zmiany i zna wszystkie zmiany aż do ostatniej wersji synchronizacji włącznie.
Funkcja CHANGETABLE(CHANGES ...) zwróci zatem wszystkie zmiany, które wystąpiły po ostatniej wersji synchronizacji.
Na poniższej ilustracji pokazano, jak funkcja CHANGETABLE(CHANGES ...) jest używana do uzyskiwania zmian.
W tym przykładzie klient A ostatnio zsynchronizował się o godzinie 9:30, podczas gdy klient B ostatnio zsynchronizował się o godzinie 10:30. O godzinie 10:00 i ponownie o godzinie 11:00 wprowadzono kilka zmian w danych. Te śledzone zmiany są podsumowywane poniżej.
CHANGETABLE(CHANGES...) Dane wyjściowe — 11:30
Klient A ostatnio zsynchronizowany o 9:30.
Identyfikator produktu Operacja Kolumny 139 Aktualizacja Nazwa, Cena 140 Usunąć - 141 Wstawiać - Klient B ostatnio zsynchronizowany o godzinie 10:30.
Identyfikator produktu Operacja Kolumny 139 Aktualizacja Cena 140 Usunąć - 141 Aktualizacja Cena
Funkcja CHANGE_TRACKING_CURRENT_VERSION()
Służy do uzyskiwania bieżącej wersji, która będzie używana podczas następnego wykonywania zapytań o zmiany. Ta wersja reprezentuje wersję ostatniej zatwierdzonej transakcji.
Funkcja CHANGE_TRACKING_MIN_VALID_VERSION()
Służy do uzyskania minimalnej prawidłowej wersji, którą klient może mieć i nadal uzyskać prawidłowe wyniki z metody CHANGETABLE(). Klient powinien sprawdzić ostatnią wersję synchronizacji względem wartości zwracanej przez tę funkcję. Jeśli ostatnia wersja synchronizacji jest mniejsza niż wersja zwrócona przez tę funkcję, klient nie będzie mógł uzyskać prawidłowych wyników z metody CHANGETABLE() i będzie musiał ponownie zainicjować.
Uzyskiwanie danych początkowych
Zanim aplikacja będzie mogła uzyskać zmiany po raz pierwszy, aplikacja musi wysłać zapytanie w celu uzyskania danych początkowych i wersji synchronizacji. Aplikacja musi uzyskać odpowiednie dane bezpośrednio z tabeli, a następnie użyć CHANGE_TRACKING_CURRENT_VERSION(), aby uzyskać wersję początkową. Ta wersja zostanie przekazana do tabeli CHANGETABLE (CHANGES ...) przy pierwszym uzyskaniu zmian.
W poniższym przykładzie pokazano, jak uzyskać początkową wersję synchronizacji i początkowy zestaw danych.
declare @synchronization_version bigint;
-- 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;
Uzyskiwanie zmian za pomocą funkcji śledzenia zmian
Aby uzyskać zmienione wiersze tabeli i informacje o zmianach, użyj metody CHANGETABLE(CHANGES...). Na przykład następujące zapytanie uzyskuje zmiany dla tabeli SalesLT.Product
.
declare @last_synchronization_version bigint;
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;
Zazwyczaj klient chce uzyskać najnowsze dane dla wiersza, a nie tylko klucze podstawowe dla wiersza. Dlatego aplikacja połączy wyniki z funkcji CHANGETABLE(CHANGES ...) z danymi w tabeli użytkownika. Na przykład następujące zapytanie łączy się z tabelą SalesLT.Product
w celu uzyskania wartości kolumn Name
i ListPrice
. Zwróć uwagę na użycie OUTER JOIN
. Jest to wymagane, aby upewnić się, że informacje o zmianie są zwracane dla tych wierszy, które zostały usunięte z tabeli użytkownika.
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;
Aby uzyskać wersję do użycia w następnym wyliczeniu zmiany, użyj CHANGE_TRACKING_CURRENT_VERSION(), jak pokazano w poniższym przykładzie.
SET @synchronization_version = CHANGE_TRACKING_CURRENT_VERSION();
Gdy aplikacja uzyskuje zmiany, musi używać zarówno metody CHANGETABLE(CHANGES...) jak i CHANGE_TRACKING_CURRENT_VERSION(), jak pokazano w poniższym przykładzie.
-- 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;
Numery wersji
Baza danych z włączonym śledzeniem zmian ma licznik wersji, który zwiększa się w miarę wprowadzania zmian w śledzonych tabelach. Każdy zmieniony wiersz ma skojarzony numer wersji. Gdy żądanie jest wysyłane do aplikacji w celu wykonania zapytania o zmiany, wywoływana jest funkcja dostarczająca numer wersji. Funkcja zwraca informacje o wszystkich zmianach wprowadzonych od tej wersji. W pewnym sensie wersja śledzenia zmian jest podobna do rowversion typu danych.
Zweryfikuj ostatnią zsynchronizowaną wersję
Informacje o zmianach są przechowywane przez ograniczony czas. Długość czasu jest kontrolowana przez parametr CHANGE_RETENTION, który można określić jako część ALTER DATABASE.
Czas określony dla CHANGE_RETENTION określa, jak często wszystkie aplikacje muszą żądać zmian z bazy danych. Jeśli aplikacja ma wartość dla last_synchronization_version starszej niż minimalna prawidłowa wersja synchronizacji dla tabeli, ta aplikacja nie może wykonać prawidłowego wyliczenia zmiany. Wynika to z faktu, że niektóre informacje o zmianach mogły zostać wyczyszczone. Zanim aplikacja uzyska zmiany przy użyciu metody CHANGETABLE(CHANGES ...), aplikacja musi zweryfikować wartość last_synchronization_version, którą planuje przekazać do metody CHANGETABLE(CHANGES ...). Jeśli wartość last_synchronization_version jest nieprawidłowa, aplikacja musi ponownie zainicjować wszystkie dane.
W poniższym przykładzie pokazano, jak zweryfikować ważność wartości last_synchronization_version
dla każdej tabeli.
-- 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;
Jak pokazano w poniższym przykładzie, ważność wartości last_synchronization_version
można sprawdzić względem wszystkich tabel w bazie danych.
-- Check all tables with change tracking enabled
IF EXISTS (
SELECT 1 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;
Korzystanie ze śledzenia kolumn
Śledzenie kolumn umożliwia aplikacjom uzyskiwanie danych tylko dla kolumn, które uległy zmianie zamiast całego wiersza. Rozważmy na przykład scenariusz, w którym tabela ma co najmniej jedną kolumnę, która jest duża, ale rzadko zmienia się; zawiera również inne kolumny, które często się zmieniają. Bez śledzenia kolumn aplikacja może określić tylko, że wiersz uległ zmianie i musiałby zsynchronizować wszystkie dane zawierające duże dane kolumn. Jednak przy użyciu śledzenia kolumn aplikacja może określić, czy duże dane kolumn zostały zmienione i zsynchronizować tylko te dane, jeśli uległy zmianie.
Informacje śledzenia kolumn są wyświetlane w kolumnie SYS_CHANGE_COLUMNS zwracanej przez funkcję CHANGETABLE(CHANGES ...).
Można użyć śledzenia kolumn, aby wartość NULL była zwracana dla kolumny, która nie została zmieniona. Jeśli kolumna może zostać zmieniona na NULL, należy zwrócić oddzielną kolumnę, aby wskazać, czy kolumna została zmieniona.
W poniższym przykładzie kolumna CT_ThumbnailPhoto
będzie NULL
, jeśli ta kolumna nie uległa zmianie. Ta kolumna może być również NULL
, ponieważ została zmieniona na NULL
— aplikacja może użyć kolumny CT_ThumbNailPhoto_Changed
, aby określić, czy kolumna została zmieniona.
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';
Uzyskiwanie spójnych i poprawnych wyników
Uzyskanie zmienionych danych dla tabeli wymaga wykonania wielu kroków. Niespójne lub nieprawidłowe wyniki mogą być zwracane, jeśli niektóre problemy nie są brane pod uwagę i obsługiwane.
Aby na przykład uzyskać zmiany wprowadzone w tabeli Sales
i tabeli SalesOrders
, aplikacja wykona następujące kroki:
Zweryfikuj ostatnią zsynchronizowaną wersję przy użyciu CHANGE_TRACKING_MIN_VALID_VERSION().
Uzyskaj wersję, którą można wykorzystać do śledzenia zmian przy następnym użyciu CHANGE_TRACKING_CURRENT_VERSION().
Uzyskaj zmiany dla tabeli
Sales
przy użyciu metody CHANGETABLE(CHANGES ...).Uzyskaj zmiany dla tabeli
SalesOrders
przy użyciu metody CHANGETABLE(CHANGES ...).
W bazie danych występują dwa procesy, które mogą mieć wpływ na wyniki zwracane przez poprzednie kroki:
Proces oczyszczania jest uruchamiany w tle i usuwa informacje śledzenia zmian starsze niż określony okres przechowywania.
Proces oczyszczania to oddzielny proces w tle, który używa okresu przechowywania określonego podczas konfigurowania śledzenia zmian dla bazy danych. Problem polega na tym, że proces oczyszczania może wystąpić w czasie między zweryfikowaniem ostatniej wersji synchronizacji a wywołaniem metody CHANGETABLE(CHANGES...). Ostatnia wersja synchronizacji, która była prawidłowa, może nie być już prawidłowa po pobraniu zmian. W związku z tym mogą zostać zwrócone nieprawidłowe wyniki.
Bieżące operacje DML, takie jak następujące, mają miejsce w tabelach Sales i
SalesOrders
:Zmiany w tabelach można wprowadzać po uzyskaniu wersji na następny raz za pomocą funkcji CHANGE_TRACKING_CURRENT_VERSION(). W związku z tym można zwrócić więcej zmian niż oczekiwano.
Transakcja może zostać zatwierdzana w czasie między wywołaniem pobierania zmian z tabeli
Sales
a wywołaniem pobierania zmian z tabeliSalesOrders
. W związku z tym wyniki tabeliSalesOrder
mogą mieć wartość klucza obcego, która nie istnieje w tabeliSales
.
Aby przezwyciężyć wymienione wcześniej wyzwania, zalecamy użycie izolacji migawki. Pomoże to zapewnić spójność informacji o zmianach i uniknąć warunków wyścigu związanych z zadaniem oczyszczania w tle. Jeśli nie używasz transakcji migawek, tworzenie aplikacji korzystającej ze śledzenia zmian może wymagać znacznie większego nakładu pracy.
Używanie izolacji migawki
Mechanizm śledzenia zmian został zaprojektowany tak, aby dobrze działał z izolacją migawkową. Należy włączyć izolację migawkową dla bazy danych. Wszystkie kroki wymagane do uzyskania zmian muszą zostać uwzględnione w transakcji migawkowej. Dzięki temu wszystkie zmiany wprowadzone w danych podczas uzyskiwania zmian nie będą widoczne dla zapytań wewnątrz transakcji migawki.
Aby uzyskać dane wewnątrz transakcji migawki, wykonaj następujące kroki:
Ustaw poziom izolacji transakcji na poziom migawki i rozpocznij transakcję.
Zweryfikuj ostatnią wersję synchronizacji przy użyciu CHANGE_TRACKING_MIN_VALID_VERSION().
Uzyskaj wersję do użycia przy następnej okazji, korzystając z CHANGE_TRACKING_CURRENT_VERSION().
Uzyskaj zmiany dla tabeli
Sales
przy użyciu metody CHANGETABLE(CHANGES ...)Uzyskaj zmiany dla tabeli
SalesOrders
przy użyciu metody CHANGETABLE(CHANGES ...)Zatwierdź transakcję.
Należy pamiętać o niektórych kwestiach, ponieważ wszystkie kroki uzyskiwania zmian znajdują się wewnątrz transakcji migawkowej.
Jeśli czyszczenie wystąpi po zweryfikowaniu ostatniej wersji synchronizacji, wyniki z CHANGETABLE(CHANGES ...) będą nadal prawidłowe, ponieważ operacje usuwania wykonywane przez oczyszczanie nie będą widoczne wewnątrz transakcji.
Wszelkie zmiany wprowadzone w tabeli
Sales
lub tabeliSalesOrders
po otrzymaniu następnej wersji synchronizacji nie będą widoczne, a wywołania metody CHANGETABLE (CHANGES ...) nigdy nie będą zwracać zmian z wersją późniejszą niż ta zwrócona przez CHANGE_TRACKING_CURRENT_VERSION(). Spójność między tabeląSales
a tabeląSalesOrders
zostanie również zachowana, ponieważ transakcje, które zostały zatwierdzone w czasie między wywołaniami metody CHANGETABLE(CHANGES ...) nie będą widoczne.
W poniższym przykładzie pokazano, jak włączono izolację migawek dla bazy danych.
-- The database must be configured to enable snapshot isolation.
ALTER DATABASE AdventureWorksLT
SET ALLOW_SNAPSHOT_ISOLATION ON;
Transakcja migawki jest używana w następujący sposób:
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
Aby uzyskać więcej informacji na temat transakcji typu snapshot, zobacz SET TRANSACTION ISOLATION LEVEL (Transact-SQL).
Czyszczenie i izolacja migawki
Włączenie izolacji migawki i śledzenia zmian w tej samej bazie danych lub w dwóch różnych bazach danych w tym samym wystąpieniu może spowodować usunięcie wygasłych wierszy w sys.syscommittab
, gdy istnieje otwarta transakcja w bazie danych z izolacją migawki. Może się to zdarzyć, ponieważ proces czyszczenia śledzenia zmian bierze pod uwagę dolny próg na poziomie całego wystąpienia (który jest bezpieczną wersją czyszczenia) podczas czyszczenia. Czynność ta jest wykonywana, aby upewnić się, że proces automatycznego oczyszczania śledzenia zmian nie usuwa żadnych wierszy, które mogą być potrzebne otwartej transakcji w bazie danych z włączoną izolacją migawkową. Zachowaj izolację migawek zatwierdzonych do odczytu oraz utrzymuj transakcje izolacji migawkowej jak najkrótsze, aby zapewnić, że wygasłe wiersze z sys.syscommittab
są czyszczone w odpowiednim czasie.
Alternatywy dla izolacji migawek
Istnieją alternatywy dla korzystania z izolacji migawek, ale wymagają one więcej pracy, aby upewnić się, że zostały spełnione wszystkie wymagania aplikacji. Aby upewnić się, że last_synchronization_version jest prawidłowa, a dane nie są usuwane przez proces oczyszczania przed uzyskaniem zmian, wykonaj następujące kroki:
Sprawdź last_synchronization_version po wywołaniach metody CHANGETABLE().
Sprawdź last_synchronization_version jako część każdego zapytania, aby uzyskać zmiany za pomocą funkcji CHANGETABLE().
Zmiany mogą wystąpić po uzyskaniu wersji synchronizacji dla następnego wyliczenia. Istnieją dwa sposoby radzenia sobie z tą sytuacją. Opcja, która jest używana, zależy od aplikacji i sposobu, w jaki może obsługiwać skutki uboczne poszczególnych podejść:
Ignoruj zmiany, które mają wersję większą niż nowa wersja synchronizacji.
Takie podejście ma efekt uboczny, że nowy lub zaktualizowany wiersz zostanie pominięty, jeśli został utworzony lub zaktualizowany przed nową wersją synchronizacji, ale następnie zaktualizowany później. Jeśli istnieje nowy wiersz, może wystąpić problem z integralnością referencyjną, jeśli w innej tabeli wystąpił wiersz, który odwoływał się do pominiętego wiersza. Jeśli istnieje zaktualizowany istniejący wiersz, wiersz zostanie pominięty i nie zostanie zsynchronizowany do następnego czasu.
Uwzględnij wszystkie zmiany, nawet te, które mają wersję większą niż nowa wersja synchronizacji.
Wiersze, które mają wersję większą niż nowa wersja synchronizacji, zostaną ponownie pobrane podczas następnej synchronizacji. Musi to być oczekiwane i obsługiwane przez aplikację.
Oprócz dwóch poprzednich opcji można opracować podejście, które łączy obie opcje w zależności od operacji. Na przykład możesz chcieć, aby aplikacja ignorowała zmiany nowsze niż następna wersja synchronizacji, w której wiersz został utworzony lub usunięty, natomiast aktualizacje nie są ignorowane.
Notatka
Wybranie podejścia, które będzie działać dla aplikacji w przypadku korzystania ze śledzenia zmian (lub dowolnego niestandardowego mechanizmu śledzenia), wymaga znacznej analizy. W związku z tym użycie izolacji migawki jest znacznie prostsze.
Jak śledzenie zmian obsługuje zmiany w bazie danych
Niektóre aplikacje korzystające ze śledzenia zmian wykonują dwukierunkową synchronizację z innym magazynem danych. Oznacza to, że zmiany wprowadzone w bazie danych programu SQL Server są aktualizowane w innym magazynie danych, a zmiany wprowadzone w innym magazynie są aktualizowane w bazie danych programu SQL Server.
Gdy aplikacja aktualizuje lokalną bazę danych ze zmianami z innego magazynu danych, aplikacja musi wykonywać następujące operacje:
Sprawdź, czy nie ma konfliktów.
Konflikt występuje, gdy te same dane są zmieniane w tym samym czasie w obu magazynach danych. Aplikacja musi mieć możliwość sprawdzenia konfliktu i uzyskania wystarczającej ilości informacji, aby umożliwić rozwiązanie konfliktu.
Przechowywanie informacji o kontekście aplikacji.
Aplikacja przechowuje dane zawierające informacje dotyczące śledzenia zmian. Te informacje będą dostępne wraz z innymi informacjami dotyczącymi śledzenia zmian w przypadku uzyskania zmian z lokalnej bazy danych. Typowym przykładem tych informacji kontekstowych jest identyfikator magazynu danych, który był źródłem zmiany.
Aby wykonać poprzednie operacje, aplikacja synchronizacji może używać następujących funkcji:
CHANGETABLE(WERSJA...)
Gdy aplikacja wprowadza zmiany, może użyć tej funkcji do sprawdzania konfliktów. Funkcja uzyskuje najnowsze informacje o śledzeniu zmian dla określonego wiersza w śledzonej tabeli zmian. Informacje dotyczące śledzenia zmian obejmują wersję ostatniego zmienionego wiersza. Te informacje umożliwiają aplikacji określenie, czy wiersz został zmieniony po ostatniej synchronizacji aplikacji.
Z użyciem CHANGE_TRACKING_CONTEXT
Aplikacja może użyć tej klauzuli do przechowywania danych kontekstowych.
Sprawdzanie konfliktów
W scenariuszu synchronizacji dwukierunkowej aplikacja kliencka musi określić, czy wiersz nie został zaktualizowany od czasu ostatniego uzyskania zmian przez aplikację.
W poniższym przykładzie pokazano, jak używać funkcji CHANGETABLE(VERSION ...) do sprawdzania konfliktów w najbardziej wydajny sposób bez oddzielnego zapytania. W tym przykładzie CHANGETABLE(VERSION ...)
określa SYS_CHANGE_VERSION
dla wiersza określonego przez @product id
.
CHANGETABLE(CHANGES ...)
można uzyskać te same informacje, ale byłoby to mniej wydajne. Jeśli wartość SYS_CHANGE_VERSION
dla wiersza jest większa niż wartość @last_sync_version
, występuje konflikt. Jeśli wystąpi konflikt, wiersz nie zostanie zaktualizowany. Sprawdzanie ISNULL()
jest wymagane, ponieważ wiersz może nie zawierać żadnych informacji o zmianie. Żadne informacje o zmianie nie istniały, gdyby wiersz nie został zaktualizowany od czasu włączenia śledzenia zmian lub od czasu wyczyszczenia informacji o zmianie.
-- 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);
Poniższy kod może sprawdzić zaktualizowaną liczbę wierszy i zidentyfikować więcej informacji o konflikcie.
-- 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
Ustawianie informacji kontekstowych
Korzystając z klauzuli WITH CHANGE_TRACKING_CONTEXT, aplikacja może przechowywać informacje kontekstowe wraz ze zmianami. Te informacje można następnie uzyskać z kolumny SYS_CHANGE_CONTEXT zwracanej przez funkcję CHANGETABLE(CHANGES ...).
Informacje kontekstowe są zwykle używane do identyfikowania źródła zmian. Jeśli można zidentyfikować źródło zmiany, te informacje mogą być używane przez magazyn danych, aby uniknąć uzyskiwania zmian podczas ponownej synchronizacji.
-- 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);
Zapewnianie spójnych i poprawnych wyników
Aplikacja musi rozważyć proces oczyszczania, gdy weryfikuje wartość @last_sync_version. Wynika to z faktu, że dane mogły zostać usunięte po wywołaniu CHANGE_TRACKING_MIN_VALID_VERSION(), ale przed dokonaniem aktualizacji.
Należy użyć izolacji migawki i wprowadzić zmiany w ramach transakcji migawki.
-- 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;
Notatka
Istnieje możliwość, że wiersz aktualizowany w ramach transakcji migawki mógł zostać zaktualizowany w innej transakcji po rozpoczęciu transakcji migawki. W takim przypadku wystąpi konflikt aktualizacji izolacji migawki, który doprowadzi do przerwania transakcji. W takim przypadku ponów próbę aktualizacji. Spowoduje to wykrycie konfliktu śledzenia zmian i brak zmian wierszy.
Śledzenie zmian i przywracanie danych
Aplikacje wymagające synchronizacji muszą rozważyć przypadek, w którym baza danych z włączonym śledzeniem zmian przywraca wcześniejszą wersję danych. Taka sytuacja może wystąpić po przywróceniu bazy danych z kopii zapasowej, gdy nastąpi przełączenie awaryjne do asynchronicznego mirrora bazy danych lub gdy wystąpi awaria podczas korzystania z przesyłania dzienników. W poniższym scenariuszu przedstawiono problem:
Tabela T1 jest ze śledzeniem zmian, a minimalna prawidłowa wersja dla tabeli to 50.
Aplikacja kliencka synchronizuje dane w wersji 100 i uzyskuje informacje o wszystkich zmianach między wersjami 50 i 100.
Dodatkowe zmiany są wprowadzane do tabeli T1 po wersji 100.
W wersji 120 występuje błąd, a administrator bazy danych przywraca bazę danych z utratą danych. Po operacji przywracania tabela zawiera dane do wersji 70, a minimalna zsynchronizowana wersja jest nadal 50.
Oznacza to, że zsynchronizowany magazyn danych zawiera dane, które nie istnieją już w podstawowym magazynie danych.
T1 jest aktualizowany wiele razy. Obecna wersja zostaje zaktualizowana do wersji 130.
Aplikacja kliencka synchronizuje się ponownie i dostarcza ostatnio zsynchronizowaną wersję 100. Klient zweryfikuje tę liczbę pomyślnie, ponieważ 100 jest większe niż 50.
Klient uzyskuje zmiany w wersji od 100 do 130. W tym momencie klient nie jest świadomy, że zmiany z zakresu od 70 do 100 nie są takie same jak wcześniej. Dane na kliencie i serwerze nie są synchronizowane.
Jeśli baza danych została odzyskana do punktu po wersji 100, nie będzie żadnych problemów z synchronizacją. Klient i serwer prawidłowo synchronizują dane w następnym interwale synchronizacji.
Śledzenie zmian nie zapewnia obsługi odzyskiwania po utracie danych. Istnieją jednak dwie opcje wykrywania tych typów problemów z synchronizacją:
Zapisz identyfikator wersji bazy danych na serwerze i zaktualizuj tę wartość za każdym razem, gdy baza danych zostanie odzyskana lub w inny sposób utraci dane. Każda aplikacja kliencka będzie przechowywać identyfikator, a każdy klient musi zweryfikować ten identyfikator podczas synchronizowania danych. Jeśli wystąpi utrata danych, identyfikatory nie będą zgodne, a klienci ponownie zainicjują. Jedną z wad jest to, że gdyby utrata danych nie przekroczyła granicy ostatniej synchronizacji, klient mógłby przeprowadzić niepotrzebne ponowne inicjowanie.
Gdy klient wysyła zapytanie o zmiany, zarejestruj numer wersji ostatniej synchronizacji dla każdego klienta na serwerze. Jeśli wystąpi problem z danymi, ostatnie zsynchronizowane numery wersji nie będą zgodne. Oznacza to, że jest wymagana ponowna inicjalizacja.
Zobacz też
- Śledzenie zmian danych (SQL Server)
- Informacje o śledzeniu zmian (SQL Server)
- Zarządzanie śledzeniem zmian (SQL Server)
- Włączanie i wyłączanie śledzenia zmian (SQL Server)
- CHANGETABLE (Transact-SQL)
- CHANGE_TRACKING_MIN_VALID_VERSION (Transact-SQL)
- CHANGE_TRACKING_CURRENT_VERSION (Transact-SQL)
- ZE CHANGE_TRACKING_CONTEXT (Transact-SQL)