Share via


Como o controle de alterações controla as alterações em um banco de dados

Alguns aplicativos que usam controle de alterações executam sincronização de duas vias com outro armazenamento de dados. Isto é, as alterações que são feitas no banco de dados do SQL Server são atualizadas no outro armazenamento de dados, e as alterações feitas no outro armazenamento são atualizadas no banco de dados do SQL Server.

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

  • Verifique os conflitos.

    Um conflito acontece quando os mesmos dados são alterados ao mesmo tempo em ambos os armazenamentos de dados. O aplicativo deve poder verificar um conflito e obter informações suficientes para permitir a solução do conflito.

  • Armazene informações de contexto de 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 foram obtidas alterações do banco de dados local. Um exemplo comum dessas informações de contexto é um identificador para o armazenamento de dados que era a origem da alteração.

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

  • CHANGETABLE(VERSION…)

    Quando um aplicativo estiver fazendo alterações, poderá usar esta função para verificar conflitos. A função obtém as últimas informações de controle de alterações por uma linha especificada em uma tabela de alteração rastreada. As informações do controle de alterações incluem a versão da última vez que a linha foi alterada. Essa informação permite que um aplicativo determine se a linha foi alterada, depois da última vez que o aplicativo foi sincronizado.

  • WITH CHANGE_TRACKING_CONTEXT

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

Verificando conflitos

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

O exemplo a seguir mostra como usar a função CHANGETABLE(VERSION …) para verificar conflitos do modo mais eficiente, sem uma consulta separada. No exemplo, CHANGETABLE(VERSION …) determina a SYS_CHANGE_VERSION para a linha especificada por @product id. CHANGETABLE(CHANGES …) pode obter a mesma informação, mas seria menos eficiente. Se o valor de SYS_CHANGE_VERSION para a linha for maior que o valor de @last_sync_version, haverá um conflito. Se houver um conflito, a linha não será atualizada. A verificação ISNULL() é necessária porque não poderia haver nenhuma informações de alteração disponível para a linha. Nenhuma informação de alteração existiria se a linha não tivesse sido atualizada, visto que o controle de alteração estava habilitado ou a informação de alteração foi limpa.

-- 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 conta de linha atualizada e 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 na coluna SYS_CHANGE_CONTEXT que é retornada por CHANGETABLE(CHANGES …).

Informações de contexto são normalmente usadas para identificar a origem das alterações. Se a origem da alteração puder ser identificada, aquela informação poderá ser usada por um armazenamento de dados para evitar a obtenção de alterações quando ele for novamente sincronizado.

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

Assegurando resultados consistentes e corretos

Um aplicativo deve considerar o processo de limpeza quando validar o valor de @ last_sync_version. Isso é porque dados podem ter sido removidos depois que CHANGE_TRACKING_MIN_VALID_VERSION () foi chamado, mas antes que a atualização fosse feita.

Observação importanteImportante

Recomendamos que você use isolamento de instantâneo e faça as alterações dentro de uma transação de 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çãoObservação

Há uma possibilidade de que a linha, que está sendo atualizada dentro da transação de instantâneo, possa ter sido atualizada em uma outra transação depois que a transação de instantâneo foi iniciada. Nesse caso, um conflito de atualização de isolamento do instantâneo acontecerá e a transação será encerrada. Se isso acontecer, tente novamente a atualização. Isso levará então a detecção de um conflito do controle de alterações e nenhuma linha será alterada.