Compartilhar via


Trabalhar com o Controle de Alterações (SQL Server)

Os aplicativos que usam o controle de alterações devem ser capazes de obter alterações controladas, aplicar essas alterações a outro armazenamento de dados e atualizar o banco de dados de origem. Este tópico descreve como executar essas tarefas e também o papel do rastreamento de alterações quando ocorre um failover e um banco de dados deve ser restaurado a partir de um backup.

Obter alterações usando funções de controle de alterações

Descreve como usar as funções de controle de alterações para obter alterações e informações sobre as alterações feitas em um banco de dados.

Sobre as funções de controle de alterações

Os aplicativos podem usar as funções a seguir para obter as alterações feitas em um banco de dados e as informações sobre as alterações:

Função CHANGETABLE(CHANGES ...)
Essa função de conjunto de linhas é usada para consultar informações de alteração. A função consulta os dados armazenados nas tabelas internas de controle de alterações. A função retorna um conjunto de resultados que contém as chaves primárias de linhas que foram alteradas junto com outras informações de alteração, como a operação, as colunas atualizadas e a versão da linha.

CHANGETABLE(CHANGES ...) usa uma última versão de sincronização como um argumento. A última versão de sincronização é obtida usando a variável @last_synchronization_version. A semântica da última versão de sincronização é a seguinte:

  • O cliente de chamada obteve alterações e sabe sobre todas as alterações até e incluindo a última versão de sincronização.

  • CHANGETABLE(CHANGES ...) retornará, portanto, todas as alterações que ocorreram após a última versão de sincronização.

    A ilustração a seguir mostra como CHANGETABLE(CHANGES ...) é usado para obter alterações.

    Exemplo de saída de consulta de controle de alterações

função CHANGE_TRACKING_CURRENT_VERSION()
É usado para obter a versão atual que será usada na próxima vez ao consultar alterações. Essa versão representa a versão da última transação confirmada.

função CHANGE_TRACKING_MIN_VALID_VERSION()
É usado para obter a versão mínima válida que um cliente pode ter e ainda obter resultados válidos de CHANGETABLE(). O cliente deve verificar a última versão de sincronização em relação ao valor retornado por essa função. Se a última versão de sincronização for menor que a versão retornada por essa função, o cliente não poderá obter resultados válidos de CHANGETABLE() e terá que reinicializar.

Obtendo dados iniciais

Antes que um aplicativo possa obter alterações pela primeira vez, o aplicativo deve enviar uma consulta para obter os dados iniciais e a versão de sincronização. O aplicativo deve obter os dados apropriados diretamente da tabela e, em seguida, usar CHANGE_TRACKING_CURRENT_VERSION() para obter a versão inicial. Essa versão será passada para CHANGETABLE(CHANGES ...) na primeira vez em que as alterações forem obtidas.

O exemplo a seguir mostra como obter a versão de sincronização inicial e o conjunto de dados inicial.

    -- 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  

Usando as funções de controle de alterações para obter alterações

Para obter as linhas alteradas para uma tabela e informações sobre as alterações, use CHANGETABLE(CHANGES...). Por exemplo, a consulta a seguir obtém alterações para a SalesLT.Product tabela.

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  
  

Normalmente, um cliente desejará obter os dados mais recentes de uma linha em vez de apenas as chaves primárias da linha. Portanto, um aplicativo uniria os resultados de CHANGETABLE(CHANGES ...) com os dados na tabela do usuário. Por exemplo, a consulta a seguir une as linhas da tabela SalesLT.Product para obter os valores das colunas Name e ListPrice . Observe o uso da função OUTER JOIN. Ela é obrigatória para garantir que as informações de alteração sejam retornadas para essas linhas que foram excluídas da tabela do usuário.

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  

Para obter a versão que será utilizada na próxima enumeração de alterações, use CHANGE_TRACKING_CURRENT_VERSION(), conforme mostrado no exemplo a seguir.

SET @synchronization_version = CHANGE_TRACKING_CURRENT_VERSION()  

Quando um aplicativo obtém alterações, ele deve usar CHANGETABLE(CHANGES...) e CHANGE_TRACKING_CURRENT_VERSION(), conforme mostrado no exemplo a seguir.

-- 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  

Números de versão

Um banco de dados que tem o controle de alterações habilitado tem um contador de versão que aumenta à medida que são feitas alterações para alterar tabelas controladas. Cada linha alterada tem um número de versão associado a ela. Quando uma solicitação é enviada a um aplicativo para consultar alterações, uma função é chamada que fornece um número de versão. A função retorna informações sobre todas as alterações que foram feitas desde essa versão. De certa forma, a versão de rastreamento de alterações é semelhante em conceito ao rowversion tipo de dados.

Validando a última versão sincronizada

As informações sobre alterações são mantidas por um tempo limitado. O período de tempo é controlado pelo parâmetro CHANGE_RETENTION que pode ser especificado como parte do ALTER DATABASE.

Lembre-se de que o tempo especificado para CHANGE_RETENTION determina com que frequência todos os aplicativos devem solicitar alterações do banco de dados. Se um aplicativo tiver um valor para last_synchronization_version mais antigo que a versão mínima de sincronização válida para uma tabela, esse aplicativo não poderá executar enumeração de alteração válida. Isso ocorre porque algumas informações de alteração podem ter sido eliminadas. Antes que um aplicativo obtenha alterações usando CHANGETABLE(CHANGES ...), o aplicativo deve validar o valor para last_synchronization_version que planeja passar para CHANGETABLE(CHANGES ...). Se o valor de last_synchronization_version não for válido, esse aplicativo deverá reinicializar todos os dados.

O exemplo a seguir mostra como verificar a validade do valor de last_synchronization_version cada tabela.

-- 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  

Como o exemplo a seguir mostra, a validade do valor de last_synchronization_version pode ser verificada em todas as tabelas no banco de dados.

-- 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  

Usando o acompanhamento de colunas

O acompanhamento de colunas permite que os aplicativos obtenham os dados apenas para as colunas que foram alteradas em vez de toda a linha. Por exemplo, considere o cenário em que uma tabela tem uma ou mais colunas grandes, mas raramente alteradas; e também tem outras colunas que mudam com frequência. Sem o acompanhamento de colunas, um aplicativo só pode determinar que uma linha foi alterada e teria que sincronizar todos os dados que incluem os dados de coluna grandes. No entanto, usando o acompanhamento de colunas, um aplicativo pode determinar se os dados de coluna grande foram alterados e sincronizar apenas os dados se eles tiverem sido alterados.

As informações de acompanhamento de coluna são exibidas na coluna SYS_CHANGE_COLUMNS retornada pela função CHANGETABLE(CHANGES ...).

O acompanhamento de colunas pode ser usado para que NULL seja retornado para uma coluna que não foi alterada. Se a coluna puder ser alterada para NULL, uma coluna separada deverá ser retornada para indicar se a coluna foi alterada.

No exemplo a seguir, a CT_ThumbnailPhoto coluna será NULL se essa coluna não tiver sido alterada. Essa coluna também pode ser NULL porque foi alterada para NULL : o aplicativo pode usar a CT_ThumbNailPhoto_Changed coluna para determinar se a coluna foi alterada.

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'  

Obtendo resultados consistentes e corretos

A obtenção dos dados alterados para uma tabela requer várias etapas. Lembre-se de que resultados inconsistentes ou incorretos poderão ser retornados se determinados problemas não forem considerados e tratados.

Por exemplo, para obter as alterações feitas em uma tabela Sales e na tabela SalesOrders, um aplicativo executaria as seguintes etapas:

  1. Valide a última versão sincronizada usando CHANGE_TRACKING_MIN_VALID_VERSION().

  2. Obtenha a versão que pode ser usada para obter alterações na próxima vez ao utilizar CHANGE_TRACKING_CURRENT_VERSION().

  3. Obtenha as alterações da tabela Vendas usando CHANGETABLE(CHANGES ...).

  4. Obtenha as alterações da tabela SalesOrders usando CHANGETABLE(CHANGES ...).

Dois processos estão ocorrendo no banco de dados que podem afetar os resultados retornados pelas etapas anteriores:

  • O processo de limpeza é executado em segundo plano e remove informações de controle de alterações mais antigas do que o período de retenção especificado.

    O processo de limpeza é um processo em segundo plano separado que usa o período de retenção especificado quando você configura o controle de alterações para o banco de dados. O problema é que o processo de limpeza pode ocorrer no tempo entre quando a última versão de sincronização foi validada e quando a chamada para CHANGETABLE(CHANGES...) é feita. Uma última versão de sincronização válida pode não ser mais válida quando as alterações forem obtidas. Portanto, os resultados incorretos podem ser retornados.

  • Operações DML em andamento estão ocorrendo nas tabelas Sales e SalesOrders, como as seguintes operações:

    • As alterações podem ser feitas nas tabelas após a versão da próxima vez ter sido obtida usando CHANGE_TRACKING_CURRENT_VERSION(). Portanto, mais alterações podem ser retornadas do que o esperado.

    • Uma transação pode ser confirmada no tempo entre a chamada para obter alterações da tabela Vendas e a chamada para obter alterações da tabela SalesOrders. Portanto, os resultados da tabela SalesOrder podem ter um valor de chave estrangeira que não existe na tabela Vendas.

Para superar os desafios listados anteriormente, recomendamos que você use o isolamento de instantâneo. Isso ajudará a garantir a consistência das informações de alteração e evitar condições de concorrência relacionadas à tarefa de limpeza em segundo plano. Caso você não use transações de instantâneo, desenvolver um aplicativo que utilize o rastreamento de alterações pode exigir significativamente mais esforço.

Usando o isolamento de instantâneo

O controle de alterações foi projetado para funcionar bem com o isolamento por snapshot. O isolamento de instantâneo deve ser habilitado para o banco de dados. Todas as etapas necessárias para obter alterações devem ser incluídas dentro de uma transação de instantâneo. Isso garantirá que todas as alterações feitas nos dados durante o processo de obtenção de alterações não fiquem visíveis para as consultas dentro da transação de instantâneo de dados.

Para obter dados dentro de uma transação de instantâneo, execute as seguintes etapas:

  1. Defina o nível de isolamento da transação como instantâneo e inicie uma transação.

  2. Valide a versão mais recente da sincronização utilizando CHANGE_TRACKING_MIN_VALID_VERSION().

  3. Obtenha a versão a ser usada na próxima vez usando CHANGE_TRACKING_CURRENT_VERSION().

  4. Obtenha as alterações da tabela Vendas usando CHANGETABLE(CHANGES ...)

  5. Obtenha as alterações da tabela Salesorders usando CHANGETABLE(CHANGES ...)

  6. Confirme a transação.

Para lembrar: todas as etapas para obter alterações estão dentro de uma transação de instantâneo.

  • Se a limpeza ocorrer após a validação da última versão de sincronização, os resultados de CHANGETABLE(CHANGES ...) ainda serão válidos, pois as operações de exclusão executadas pela limpeza não estarão visíveis dentro da transação.

  • Todas as alterações feitas na tabela Vendas ou na tabela SalesOrders após a próxima versão de sincronização forem obtidas não estarão visíveis e as chamadas para CHANGETABLE(CHANGES ...) nunca retornarão alterações com uma versão posterior à que foi retornada por CHANGE_TRACKING_CURRENT_VERSION(). A consistência entre a tabela Vendas e a tabela SalesOrders também será mantida, pois as transações que foram confirmadas no tempo entre chamadas para CHANGETABLE(CHANGES ...) não estarão visíveis.

O exemplo a seguir mostra como o isolamento instantâneo está ativado para um banco de dados.

-- The database must be configured to enable snapshot isolation.  
ALTER DATABASE AdventureWorksLT  
    SET ALLOW_SNAPSHOT_ISOLATION ON;  

Uma transação de instantâneo é usada da seguinte maneira:

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  

Para obter mais informações sobre transações do tipo instantâneo, consulte SET TRANSACTION ISOLATION LEVEL (Transact-SQL).

Alternativas ao uso do isolamento por imagem instantânea

Há alternativas para o uso de isolamento por instantâneo, mas elas exigem mais trabalho para garantir que todos os requisitos da aplicação sejam atendidos. Para garantir que o last_synchronization_version seja válido e que os dados não sejam removidos pelo processo de limpeza antes que as alterações sejam obtidas, faça o seguinte:

  1. Verifique last_synchronization_version após as chamadas para CHANGETABLE().

  2. Verifique last_synchronization_version como parte de cada consulta para obter alterações usando CHANGETABLE().

As alterações podem ocorrer depois que a versão de sincronização para a próxima enumeração for obtida. Há duas maneiras de lidar com essa situação. A opção usada depende do aplicativo e de como ele pode lidar com os efeitos colaterais de cada abordagem:

  • Ignore as alterações que têm uma versão maior que a nova versão de sincronização.

    Essa abordagem tem o efeito colateral de que uma linha nova ou atualizada seria ignorada se fosse criada ou atualizada antes da nova versão de sincronização, mas depois atualizada. Se houver uma nova linha, um problema de integridade referencial poderá ocorrer se houver uma linha em outra tabela criada que referencie a linha ignorada. Se houver uma linha existente atualizada, a linha será ignorada e não sincronizada até a próxima vez.

  • Inclua todas as alterações, mesmo aquelas que têm uma versão maior que a nova versão de sincronização.

    As linhas que têm uma versão maior que a nova versão de sincronização serão obtidas novamente na próxima sincronização. Isso deve ser esperado e manipulado pelo aplicativo.

Além das duas opções anteriores, você pode criar uma abordagem que combine as duas opções, dependendo da operação. Por exemplo, talvez você queira um aplicativo para o qual é melhor ignorar as alterações mais recentes do que a próxima versão de sincronização na qual a linha foi criada ou excluída, mas as atualizações não são ignoradas.

Observação

Escolher a abordagem que funcionará para o aplicativo quando você estiver usando o controle de alterações (ou qualquer mecanismo de acompanhamento personalizado), requer uma análise significativa. Portanto, é muito mais fácil usar o isolamento de snapshot.

Como o rastreamento de alterações lida com mudanças em um banco de dados

Alguns aplicativos que usam o controle de alterações executam a sincronização bidirecional com outro armazenamento de dados. Ou seja, as alterações feitas no banco de dados do SQL Server são atualizadas no outro armazenamento de dados e as alterações feitas no outro repositório são atualizadas no banco de dados do SQL Server.

Quando um aplicativo atualiza o banco de dados local com alterações de outro armazenamento de dados, o aplicativo deve executar as seguintes operações:

  • Verifique se há conflitos.

    Um conflito ocorre quando os mesmos dados são alterados ao mesmo tempo em ambos os armazenamentos de dados. O aplicativo deve ser capaz de verificar se há um conflito e obter informações suficientes para permitir que o conflito seja resolvido.

  • Armazenar informações de contexto do aplicativo.

    O aplicativo armazena dados que têm as informações de controle de alterações. Essas informações estariam disponíveis junto com outras informações de controle de alterações quando as alterações foram obtidas do banco de dados local. Um exemplo comum dessas informações contextuais é um identificador para o armazenamento de dados que foi a fonte da alteração.

Para executar as operações anteriores, um aplicativo de sincronização pode usar as seguintes funções:

  • CHANGETABLE(VERSION...)

    Quando um aplicativo está fazendo alterações, ele pode usar essa função para verificar se há conflitos. A função obtém as informações mais recentes de controle de alterações para uma linha especificada em uma tabela controlada por alterações. As informações de controle de alterações incluem a versão da linha que foi alterada pela última vez. Essas informações permitem que um aplicativo determine se a linha foi alterada após a última vez em que o aplicativo foi sincronizado.

  • COM CONTEXTO_DE_RASTREAMENTO_DE_ALTERAÇÕES

    Um aplicativo pode usar essa cláusula para armazenar dados de contexto.

Verificando se há conflitos

Em um cenário de sincronização bidirecional, o aplicativo cliente deve determinar se uma linha não foi atualizada desde a última vez que o aplicativo obteve as alterações.

O exemplo a seguir mostra como usar a função CHANGETABLE(VERSION ...) para verificar se há conflitos da maneira mais eficiente, sem uma consulta separada. No exemplo, CHANGETABLE(VERSION ...) determina SYS_CHANGE_VERSION para a linha especificada por @product id. CHANGETABLE(CHANGES ...) pode obter as mesmas informações, mas isso seria menos eficiente. Se o valor da linha SYS_CHANGE_VERSION for maior que o valor de @last_sync_version, haverá um conflito. Se houver um conflito, a linha não será atualizada. A ISNULL() verificação é necessária porque pode não haver informações de alteração disponíveis para a linha. Nenhuma informação de alteração existiria se a linha não tivesse sido atualizada desde que o controle de alterações foi habilitado ou desde que as informações de alteração foram limpas.

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

O código a seguir pode verificar a contagem de linhas atualizada e pode identificar mais informações sobre o conflito.

-- 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  

Configurando informações de contexto

Usando a cláusula WITH CHANGE_TRACKING_CONTEXT, um aplicativo pode armazenar informações de contexto junto com as informações de alteração. Essas informações podem ser obtidas da coluna SYS_CHANGE_CONTEXT retornada por CHANGETABLE(CHANGES ...).

As informações de contexto normalmente são usadas para identificar a origem das alterações. Se a origem da alteração puder ser identificada, essas informações poderão ser usadas por um armazenamento de dados para evitar a obtenção de alterações quando elas forem sincronizadas novamente.

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

Garantindo resultados consistentes e corretos

Um aplicativo deve considerar o processo de limpeza quando valida o valor de @last_sync_version. Isso ocorre porque os dados podem ter sido removidos depois que CHANGE_TRACKING_MIN_VALID_VERSION() foi chamado, mas antes da atualização ser feita.

Importante

Recomendamos que você use o isolamento de instantâneos e faça as alterações dentro de uma transação por instantâneo.

-- 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  

Observação

Há a possibilidade de que a linha que está sendo atualizada dentro da transação de instantâneo possa ter sido atualizada em outra transação depois que a transação de instantâneo foi iniciada. Nesse caso, ocorrerá um conflito de atualização de isolamento por instantâneo e a transação será encerrada. Se isso acontecer, tente novamente a atualização. Isso fará com que um conflito no controle de alterações seja detectado e nenhuma linha seja modificada.

Rastreamento de Alterações e Restauração de Dados

Os aplicativos que exigem sincronização devem considerar o caso em que um banco de dados que tem o controle de alterações habilitado é revertido para uma versão anterior dos dados. Isso pode ocorrer depois que um banco de dados é restaurado de um backup, quando há um failover em um espelho de banco de dados assíncrono ou quando há uma falha ao usar o envio de logs. O cenário a seguir ilustra o problema:

  1. A tabela T1 está com controle de alterações e a versão mínima válida para a tabela é 50.

  2. Um aplicativo cliente sincroniza dados na versão 100 e obtém informações sobre todas as alterações entre as versões 50 e 100.

  3. Alterações adicionais são feitas na tabela T1 após a versão 100.

  4. Na versão 120, há uma falha e o administrador do banco de dados restaura o banco de dados com perda de dados. Após a operação de restauração, a tabela contém dados até a versão 70 e a versão mínima sincronizada ainda é 50.

    Isso significa que o armazenamento de dados sincronizado tem dados que não existem mais no armazenamento de dados primário.

  5. T1 é atualizado muitas vezes. Isso leva a versão atual para 130.

  6. O aplicativo cliente sincroniza novamente e fornece uma última versão sincronizada de 100. O cliente valida esse número com êxito porque 100 é maior que 50.

    O cliente obtém alterações entre as versões 100 e 130. Neste ponto, o cliente não está ciente de que as alterações entre 70 e 100 não são as mesmas de antes. Os dados no cliente e no servidor não são sincronizados.

Observe que, se o banco de dados foi recuperado para um ponto após a versão 100, não haveria problemas com a sincronização. O cliente e o servidor sincronizariam os dados corretamente durante o próximo intervalo de sincronização.

O controle de alterações não fornece suporte para recuperação da perda de dados. No entanto, há duas opções para detectar esses tipos de problemas de sincronização:

  • Armazene uma ID de versão do banco de dados no servidor e atualize esse valor sempre que um banco de dados for recuperado ou perder dados. Cada aplicativo cliente armazenaria a ID e cada cliente teria que validar essa ID quando sincronizasse os dados. Se ocorrer perda de dados, as IDs não corresponderão e os clientes reinicializarão. Uma desvantagem é que, se a perda de dados não tiver cruzado o último limite sincronizado, o cliente poderá fazer reinicialização desnecessária.

  • Quando um cliente consulta alterações, registre o último número de versão de sincronização para cada cliente no servidor. Se houver um problema com os dados, os últimos números de versão sincronizados não corresponderão. Isso indica que uma reinicialização é necessária.

Consulte Também

Rastrear alterações de dados (SQL Server)
Sobre o controle de alterações (SQL Server)
Gerenciar o controle de alterações (SQL Server)
Habilitar e desabilitar o controle de alterações (SQL Server)
CHANGETABLE (Transact-SQL)
CHANGE_TRACKING_MIN_VALID_VERSION (Transact-SQL)
CHANGE_TRACKING_CURRENT_VERSION (Transact-SQL)
WITH CHANGE_TRACKING_CONTEXT (Transact-SQL)