Работа с отслеживанием изменений (SQL Server)
Область применения: SQL Server
База данных SQL Azure Управляемый экземпляр SQL Azure
Приложения, в которых используется отслеживание изменений, должны иметь возможность получать отслеженные изменения, применять эти изменения к другому хранилищу данных и обновлять базу данных-источник. В этой статье описывается, как выполнять эти задачи, а также роль, которую отслеживание изменений играет при резервном переключении, когда необходимо восстановить базу данных из резервной копии.
Получайте изменения с помощью функций отслеживания изменений
Описывает, как использовать функции отслеживания изменений, чтобы получить изменения и сведения об изменениях, произведенных в базе данных.
Сведения о функциях отслеживания изменений
Чтобы получить изменения из базы данных и сведения об этих изменениях, приложения могут использовать следующие функции.
Функция CHANGETABLE(CHANGES ...)
Эта функция, возвращающая набор строк, используется для запроса информации об изменениях. Функция запрашивает данные, хранящиеся во внутренних таблицах отслеживания изменений. Она возвращает результирующий набор, содержащий первичные ключи измененных строк, а также другие сведения: операцию, число обновленных столбцов и версии строк.
Функция CHANGETABLE(CHANGES ...) получает в качестве аргумента последнюю версию синхронизации. Версию последней синхронизации можно получить с помощью переменной @last_synchronization_version
. Семантика последней версии синхронизации выглядит следующим образом.
Вызывающий клиент получает сведения обо всех изменениях, происшедших до момента последней синхронизированной версии включительно.
Функция CHANGETABLE(CHANGES ...) поэтому возвращает сведения обо всех изменениях, произошедших после последней версии синхронизации.
Ниже показано, как функция CHANGETABLE(CHANGES ...) используется для получения изменений.
В этом примере клиент A последний синхронизирован в 9:30, а клиент B последний синхронизирован в 10:30. В 10:00 и снова в 11:00 были внесены некоторые изменения в данные. Эти отслеживаемые изменения приведены ниже.
CHANGETABLE(CHANGES...) Вывод — 11:30 AM
Клиент A был синхронизирован последний раз в 9:30 утра.
Код продукта Операция Столбцы 139 Обновить Имя, цена 140 Удалить - 141 Вставить - Клиент B был последний раз синхронизирован в 10:30.
Код продукта Операция Столбцы 139 Обновить Цена 140 Удалить - 141 Обновить Цена
Функция CHANGE_TRACKING_CURRENT_VERSION()
Используется для получения текущей версии, которая будет использоваться при следующем запросе изменений. Эта версия представляет версию последней зафиксированной транзакции.
Функция CHANGE_TRACKING_MIN_VALID_VERSION()
Используется для получения минимальной допустимой версии, которую может иметь клиент и по-прежнему получать допустимые результаты из CHANGETABLE(). Клиент должен сравнить последнюю версию синхронизации со значением, возвращенным этой функцией. Если последняя версия синхронизации меньше, чем версия, возвращаемая этой функцией, клиент не сможет получить достоверные результаты из функции CHANGETABLE() и должен будет переинициализировать.
Получение исходных данных
Прежде чем приложение в первый раз получит изменения, оно должно выполнить запрос для получения первоначальных данных и версии синхронизации. Приложение должно получить соответствующие данные напрямую из таблицы, а затем вызвать функцию CHANGE_TRACKING_CURRENT_VERSION() для получения первоначальной версии. Эта версия передается функции CHANGETABLE(CHANGES ...) при первом получении изменений.
В следующем примере показано получение первоначальной версии синхронизации и первоначального набора данных.
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;
Использование функций отслеживания изменений для получения изменений
Чтобы получить измененные строки для таблицы и сведения об изменениях, используйте CHANGETABLE(CHANGES...). Например, следующий запрос получает изменения для 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;
Как правило, клиенту нужно получить последние данные строки, а не просто первичные ключи. Поэтому приложение соединяет результаты запроса функции CHANGETABLE(CHANGES ...) с данными в пользовательской таблице. Например, следующий запрос соединяется с таблицей SalesLT.Product
, чтобы получить значения столбцов Name
и ListPrice
. Обратите внимание на использование OUTER JOIN
. Это требуется, чтобы убедиться, что возвращаются сведения об изменениях в строках, удаленных из пользовательской таблицы.
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;
Чтобы получить версию, которая будет использоваться в следующем перечислении изменений, используется функция CHANGE_TRACKING_CURRENT_VERSION(), как показано в следующем примере.
SET @synchronization_version = CHANGE_TRACKING_CURRENT_VERSION();
Когда приложение получает изменения, оно должно использовать как функцию CHANGETABLE(CHANGES...), так и CHANGE_TRACKING_CURRENT_VERSION(), как показано в следующем примере.
-- 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;
Номера версий
База данных, для которой включено отслеживание изменений, содержит счетчик версий, который увеличивается при каждом изменении отслеживаемых таблиц. Каждой изменяемой строке присваивается собственный номер версии. Когда в приложение отправляется запрос изменений, вызывается функция, возвращающая номер версии. Эта функция возвращает сведения обо всех изменениях, которые были сделаны после этой версии. В некотором роде версия отслеживания изменений напоминает тип данных rowversion .
Проверка последней синхронизированной версии
Сведения об изменениях хранятся ограниченное время. Продолжительность времени контролируется параметром CHANGE_RETENTION, который может быть указан в операторе ALTER DATABASE.
Время, указанное для CHANGE_RETENTION, определяет, насколько часто все приложения должны запрашивать изменения из базы данных. Если приложение имеет значение для last_synchronization_version , которое старше минимальной допустимой версии синхронизации для таблицы, это приложение не может выполнить допустимое перечисление изменений. Это объясняется тем, что некоторые данные изменений могли быть удалены. Прежде чем приложение получает изменения с помощью CHANGETABLE(CHANGES ...), приложение должно проверить значение last_synchronization_version, что оно планирует передать в CHANGETABLE(CHANGES ...). Если значение last_synchronization_version недопустимо, это приложение должно повторно инициализировать все данные.
В следующем примере показано, как проверять достоверность значения last_synchronization_version
для каждой таблицы.
-- 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;
Как показано в следующем примере, достоверность значения last_synchronization_version
можно проверить для всех таблиц в базе данных.
-- 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;
Использование отслеживания столбцов
Отслеживание столбцов позволяет приложениям получать изменившиеся данные не всей строки, а только одного столбца. Например, рассмотрим ситуацию, когда в таблице имеются один или два больших, но редко изменяющихся столбца и другие столбцы, значения которых часто меняются. Не применяя отслеживание столбцов, приложение может только определить изменение строки и синхронизировать все данные, включая данные больших столбцов. Но с помощью отслеживания столбцов приложение может определить, в каких столбцах изменились значения, и синхронизировать только изменившиеся данные.
Сведения об отслеживании столбцов отображаются в столбце SYS_CHANGE_COLUMNS, который возвращается функцией CHANGETABLE(CHANGES ...).
Отслеживание столбцов можно использовать, чтобы значение NULL возвращалось для столбца, который не изменился. Если столбец можно изменить на NULL, необходимо возвратить отдельный столбец, который указывает, изменился ли столбец.
В следующем примере столбец будет иметь CT_ThumbnailPhoto
значение, NULL
если этот столбец не изменился. Этот столбец может также принимать значение NULL
, потому что он был изменен на NULL
, поэтому приложение может использовать столбец CT_ThumbNailPhoto_Changed
, чтобы определить, происходили ли изменения.
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';
Получение согласованных и правильных результатов
Для получения измененных данных для таблицы требуется несколько шагов. Несогласованные или неправильные результаты могут быть возвращены, если некоторые проблемы не рассматриваются и обрабатываются.
Например, чтобы получить изменения, внесенные в таблицу Sales
и SalesOrders
таблицу, приложение выполнит следующие действия:
Для проверки последней синхронизированной версии используйте функцию CHANGE_TRACKING_MIN_VALID_VERSION().
Получить версию, которая будет использована для получения изменений в следующий раз, с помощью функции CHANGE_TRACKING_CURRENT_VERSION().
Получите изменения таблицы
Sales
с использованием CHANGETABLE(CHANGES ...).Получите изменения для таблицы
SalesOrders
с помощью CHANGETABLE(CHANGES ...).
В базе данных выполняются следующие два процесса, которые могут повлиять на результаты, возвращаемые на предыдущих шагах.
Процесс очистки выполняется в фоновом режиме и удаляет данные отслеживания изменений старше указанного срока хранения.
Процесс очистки является отдельным фоновым процессом и руководствуется сроком хранения, заданным при настройке отслеживания изменений в базе данных. Проблема заключается в том, что процесс очистки может происходить в период между валидацией последней версии синхронизации и вызовом функции CHANGETABLE(CHANGES...). Последняя версия синхронизации, которая была действительна, может быть недействительна к моменту получения изменений. Поэтому функция может возвратить неверные результаты.
Текущие операции DML выполняются в таблицах Sales и
SalesOrders
, например, следующие:В таблицы можно вносить изменения после получения версии для следующего раза с помощью функции CHANGE_TRACKING_CURRENT_VERSION(). Следовательно, функция может вернуть больше изменений, чем ожидалось.
Транзакция может быть завершена в тот промежуток времени, который проходит между вызовом получения изменений из таблицы
Sales
и вызовом получения изменений из таблицыSalesOrders
. Таким образом, результаты таблицыSalesOrder
могут иметь значение внешнего ключа, которое не существует вSales
таблице.
Для преодоления приведенных выше проблем рекомендуется применять изоляцию моментального снимка. Это позволит обеспечить согласованность сведений об изменениях и избежать соперничества при выполнении задач фоновой очистки. Если вы не используете транзакции моментальных снимков, разработка приложения, использующего отслеживание изменений, может потребовать значительно больше усилий.
Используйте изоляцию моментальных снимков
Отслеживание изменений было разработано для эффективного взаимодействия с изоляцией моментального снимка. Для базы данных необходимо включить изоляцию моментальных снимков. Все шаги, необходимые для получения изменений, должны быть включены в мгновенную транзакцию. Это гарантирует, что все изменения, внесенные в данные в процессе получения изменений, не будут видны запросам внутри транзакции моментального снимка.
Чтобы получить данные в транзакции моментального снимка, выполните следующие действия.
Установите уровень изоляции транзакции на уровень моментальных снимков и запустите транзакцию.
Проверьте последнюю версию синхронизации с помощью функции CHANGE_TRACKING_MIN_VALID_VERSION().
Получите версию, которая будет использоваться в следующий раз, с помощью функции CHANGE_TRACKING_CURRENT_VERSION().
Получить изменения для таблицы
Sales
с помощью CHANGETABLE(CHANGES ...)Получите изменения для таблицы
SalesOrders
с помощью CHANGETABLE(CHANGES ...)Зафиксируйте транзакцию.
Некоторые моменты, которые следует помнить: все действия для получения изменений находятся внутри транзакции с мгновенными снимками.
Если очистка происходит после последней версии синхронизации, результаты из CHANGETABLE(CHANGES ...) по-прежнему будут допустимы, так как операции удаления, выполняемые очисткой, не будут отображаться внутри транзакции.
Любые изменения, внесенные в
Sales
таблицу илиSalesOrders
таблицу после получения следующей версии синхронизации, не будут видны, и вызовы CHANGETABLE(CHANGES ...) никогда не будут возвращать изменения с версией позже, чем возвращенная CHANGE_TRACKING_CURRENT_VERSION(). Согласованность междуSales
таблицей иSalesOrders
таблицей также будет поддерживаться, так как транзакции, зафиксированные во время между вызовами CHANGETABLE(CHANGES ...), не будут видны.
В следующем примере показано включение изоляции моментального снимка в базе данных.
-- The database must be configured to enable snapshot isolation.
ALTER DATABASE AdventureWorksLT
SET ALLOW_SNAPSHOT_ISOLATION ON;
Транзакция типа "моментальный снимок" используется следующим образом.
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
Дополнительные сведения о транзакциях моментальных снимков см. в разделе SET TRANSACTION ISOLATION LEVEL (Transact-SQL).
Очистка и изоляция снимков
Включение изоляции моментальных снимков и отслеживания изменений в одной базе данных или в двух разных базах данных в одном экземпляре может привести к тому, что процесс очистки оставит строки sys.syscommittab
с истекшим сроком действия, если в базе данных с изоляцией моментальных снимков есть открытая транзакция. Это может произойти, поскольку процесс очистки с отслеживанием изменений учитывает нижнюю конечную точку в масштабе всего экземпляра (которая является безопасной версией очистки) при выполнении очистки. Это делается для того, чтобы процесс автоматической очистки отслеживания изменений не удалял строки, которые могут понадобиться открытой транзакции в базе данных с включенной изоляцией моментального снимка. Сохраняйте транзакции уровня изоляции повторяемого чтения и изоляции моментальных снимков как можно короче, чтобы обеспечить своевременную очистку просроченных строк из sys.syscommittab
.
Альтернативы изоляции мгновенных снимков
Существуют альтернативы использованию изоляции моментального снимка, но для их реализации требуется больше усилий, чтобы соответствовать всем требованиям приложений. Чтобы убедиться, что last_synchronization_version является допустимым и данные не удаляются процессом очистки перед получением изменений, выполните следующие действия.
Проверьте параметр last_synchronization_version после вызовов функции CHANGETABLE().
Проверяйте параметр last_synchronization_version в составе каждого запроса, чтобы получить изменения с помощью функции CHANGETABLE().
Изменения могут происходить после получения версии синхронизации для следующего перечисления. Для обхода этой ситуации существует два способа. Используемый вариант зависит от приложения и от того, как оно может справляться с побочными эффектами каждого подхода.
Пропускайте изменения с версиями больше, чем новая версия синхронизации.
Побочный эффект этого подхода заключается в том, что новая или обновленная строка будет пропущена, если она была создана или обновлена перед версией новой синхронизации, а затем обновлена после нее. Если есть новая строка, проблема целостности ссылок может возникнуть, если в другой таблице существовала строка, которая ссылалась на пропущенную строку. Если есть существующая обновленная строка, она будет пропущена и не синхронизирована до следующей попытки.
Включайте все изменения, даже с версиями, которые больше версии синхронизации.
Строки, у которых версия больше новой версии синхронизации, будут снова получены при следующей синхронизации. Приложение должно предполагать такую ситуацию и обрабатывать ее.
Кроме двух предыдущих вариантов можно разработать подход, сочетающий обе возможности в зависимости от операции. Например, может потребоваться приложение, в котором лучше игнорировать изменения, более новые, чем следующая версия синхронизации, в которой строка была создана или удалена, но обновления, при этом, не игнорируются.
Примечание.
Выбор оптимального подхода для приложения, работающего с отслеживанием изменений, или любого пользовательского средства отслеживания изменений требует тщательного анализа. Поэтому намного проще использовать изоляцию моментального снимка.
Как отслеживание изменений обрабатывает изменения в базе данных
Некоторые приложения, использующие отслеживание изменений, выполняют двустороннюю синхронизацию с другими хранилищами данных. То есть изменения, внесенные в базу данных SQL Server, обновляются в другом хранилище данных, а изменения, внесенные в другое хранилище, обновляются в базе данных SQL Server.
Если приложение обновляет локальную базу данных изменениями, сделанными в другом хранилище данных, оно должно выполнить следующие операции.
Проверить наличие конфликтов.
Конфликт возникает, когда одни и те же данные одновременно изменяются в обоих хранилищах данных. Приложение должно иметь возможность проверить наличие конфликта и получить достаточно информации для его разрешения.
Сохранить контекстные сведения приложения.
Приложение хранит данные, включающие информацию об отслеживании изменений. Эта информация должна быть доступна вместе с другими данными отслеживания изменений, если изменения были получены из локальной базы данных. Типичный пример таких контекстных сведений – идентификатор хранилища данных, которое было источником изменений.
Для выполнения вышеуказанных операций приложение синхронизации может использовать следующие функции:
CHANGETABLE(VERSION...)
Когда приложение выполняет изменения, оно может использовать эту функцию для проверки конфликтов. Функция получает последние данные отслеживания изменений для заданной строки в таблице с отслеживанием изменений. Информация об отслеживании изменений включает версию строки, которая была изменена в последний раз. Это позволяет приложению определить, изменилась ли строка с момента последней синхронизации приложения.
С ИСПОЛЬЗОВАНИЕМ КОНТЕКСТА ОТСЛЕЖИВАНИЯ ИЗМЕНЕНИЙ
Приложение может использовать это предложение для хранения контекстных данных.
Проверка наличия конфликтов
В двустороннем сценарии синхронизации клиентское приложение должно определить, не была ли строка обновлена с момента последнего получения изменений приложением.
В следующем примере показано использование функции CHANGETABLE(VERSION ...) для проверки конфликтов самым эффективным способом — без отдельного запроса. В примере CHANGETABLE(VERSION ...)
определяет SYS_CHANGE_VERSION
для строки, заданной аргументом @product id
.
CHANGETABLE(CHANGES ...)
может получить те же сведения, но это будет менее эффективным. Если значение SYS_CHANGE_VERSION
строки больше значения @last_sync_version
, возникает конфликт. Если возникает конфликт, строка не будет обновлена. Проверка ISNULL()
необходима, поскольку для строки может не иметься информации об изменениях. Информация об изменении отсутствовала бы, если строка не была обновлена с момента включения отслеживания изменений или с момента очистки информации об изменениях.
-- 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);
Следующий код проверяет обновленное число строк и может предоставить более подробные сведения о конфликте.
-- 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
Настройка сведений о контексте
С помощью предложения WITH CHANGE_TRACKING_CONTEXT приложение может хранить контекстные данные вместе с информацией об изменениях. Затем эти данные можно получить в столбце SYS_CHANGE_CONTEXT, который возвращает функция CHANGETABLE(CHANGES ...).
Контекстные данные обычно используются для определения источника изменений. Если источник изменений можно определить, эти данные могут использоваться хранилищем данных, чтобы не получать изменения при повторной синхронизации.
-- 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);
Обеспечение согласованности и правильности результатов
Приложение должно учитывать процесс очистки при проверке значения параметра @last_sync_version. Это объясняется тем, что данные могли быть удалены после вызова функции CHANGE_TRACKING_MIN_VALID_VERSION(), но перед тем, как было выполнено обновление.
Следует использовать изоляцию мгновенных снимков и вносить изменения в рамках транзакции с использованием мгновенных снимков.
-- 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;
Примечание.
Существует вероятность того, что обновляемая в рамках транзакции моментальных снимков строка уже была обновлена в другой транзакции после начала транзакции моментальных снимков. В этом случае произойдет конфликт обновления при изоляции снапшотов, который приведет к завершению транзакции. В этом случае повторите попытку обновления. В дальнейшем это приведет к обнаружению конфликта отслеживания изменений, и ни одна из строк не будет обновлена.
Отслеживание изменений и восстановление данных
Приложения, для которых необходима синхронизация, должны учитывать возможность восстановления базы данных, для которой включено отслеживание изменений, в предыдущее состояние. Это может произойти после восстановления базы данных из резервной копии, при переключении на асинхронное зеркальное отображение базы данных или при сбое при использовании доставки журналов. Эту проблему иллюстрирует следующий сценарий.
Таблица T1 отслеживает внесенные изменения, а минимально допустимая версия таблицы — 50.
Клиентское приложение синхронизирует данные на версии 100 и получает информацию о всех изменениях между версиями 50 и 100.
После версии 100 в таблицу Т1 были внесены дополнительные изменения.
В версии 120 возникает сбой, а администратор базы данных восстанавливает базу данных с потерей данных. После завершения восстановления таблица содержит данные до версии 70, а минимальная синхронизированная версия по-прежнему равна 50.
Это означает, что синхронизированное хранилище данных содержит данные, которых уже нет в первичном хранилище.
Таблица Т1 обновлялась многократно. Это довело текущую версию до 130.
Клиентское приложение снова синхронизируется и передает последний синхронизированный номер 100. Проверка этого номера клиентом происходит успешно, так как 100 больше 50.
Клиент получает изменения между версиями 100 и 130. На этом этапе клиент не знает, что изменения в диапазоне от 70 до 100 не совпадают с ранее. Данные на клиенте и сервере не синхронизируются.
Если база данных была восстановлена до точки после версии 100, не будет проблем с синхронизацией. Клиент и сервер должны правильно синхронизировать данные во время следующего интервала синхронизации.
Отслеживание изменений не обеспечивает поддержку восстановления после потери данных. Однако существует две возможности обнаружения проблем синхронизации такого рода.
Сохраните идентификатор версии базы данных на сервере и обновляйте это значение при каждом восстановлении данных или их потере, вызванной любыми другими причинами. Этот идентификатор должно хранить и проверять во время синхронизации данных каждое клиентское приложение. Если возникает потеря данных, идентификаторы не будут совпадать, и клиенты будут повторно инициализироваться. Один из недостатков заключается в том, что если потеря данных не пересекла последнюю синхронизированную границу, клиент может сделать ненужную повторную инициализацию.
Когда клиент делает запрос об изменениях, сохраните номер последней версии синхронизации каждого клиента сервера. Если возникла проблема с данными, последние синхронизированные номера версий не совпадут. Это будет означать, что необходима повторная инициализация.
См. также
- Отслеживание изменений данных (SQL Server)
- Сведения об отслеживании изменений (SQL Server)
- Управление отслеживанием изменений (SQL Server)
- Включение и отключение отслеживания изменений (SQL Server)
- CHANGETABLE (Transact-SQL)
- CHANGE_TRACKING_MIN_VALID_VERSION (Transact-SQL)
- ТЕКУЩАЯ_ВЕРСИЯ_ОТСЛЕЖИВАНИЯ_ИЗМЕНЕНИЙ (Transact-SQL)
- С ИСПОЛЬЗОВАНИЕМ CHANGE_TRACKING_CONTEXT (Transact-SQL)