Compartir a través de


Cómo el seguimiento de cambios controla los cambios en una base de datos

Algunas aplicaciones que utilizan el seguimiento de cambios realizan una sincronización bidireccional con otro almacén de datos. Es decir, los cambios que se realizan en la base de datos de SQL Server se actualizan en el otro almacén de datos y los que se realizan en este se actualizan en la base de datos de SQL Server.

Cuando una aplicación actualiza la base de datos local con los cambios de otro almacén de datos, debe realizar las operaciones siguientes:

  • Comprobar si hay conflictos.

    Un conflicto se produce cuando los mismos datos se cambian en ambos almacenes de datos al mismo tiempo. La aplicación debe poder comprobar si hay un conflicto y obtener suficiente información para permitir que se resuelva.

  • Almacenar información de contexto de la aplicación.

    La aplicación almacena los datos que tienen la información de seguimiento de cambios. Esta información estaría disponible junto con otra referente al seguimiento de cambios cuando los cambios se obtuvieran de la base de datos local. Un ejemplo común de esta información contextual es un identificador del almacén de datos que fue el origen del cambio.

Para realizar las operaciones anteriores, una aplicación de sincronización puede utilizar las funciones siguientes:

  • CHANGETABLE(VERSION…)

    Cuando una aplicación está realizando cambios, puede utilizar esta función para comprobar si hay conflictos. La función obtiene la información de seguimiento de cambios más reciente para una fila especificada de la tabla de cambios sometida a seguimiento. La información de seguimiento de cambios incluye el número de versión correspondiente a la fila que se cambió en último lugar. Esta información permite que una aplicación determine si la fila se cambió después de que la aplicación se sincronizara por última vez.

  • WITH CHANGE_TRACKING_CONTEXT

    Una aplicación puede utilizar esta cláusula para almacenar los datos de contexto.

Comprobar si hay conflictos

En un escenario de sincronización bidireccional, la aplicación cliente debe determinar si una fila no ha sido actualizada desde que la aplicación obtuvo los cambios por última vez.

En el ejemplo siguiente se muestra cómo utilizar la función CHANGETABLE(VERSION …) para comprobar si hay conflictos de la manera más eficaz, sin una consulta independiente. En el ejemplo, CHANGETABLE(VERSION …) determina la SYS_CHANGE_VERSION para la fila especificada por @product id. CHANGETABLE(CHANGES …) puede obtener la misma información, pero eso sería menos eficiente. Si el valor de SYS_CHANGE_VERSION para la fila es mayor que el valor de @last_sync_version, hay un conflicto. Si hay un conflicto, la fila no se actualizará. La comprobación ISNULL() se requiere porque podría no haber ninguna información de cambios disponible para la fila. No existiría ninguna información de cambios si la fila no se hubiera actualizado desde que se habilitó el seguimiento de cambios o desde que se limpió la información de los cambios.

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

El código siguiente puede comprobar el recuento de filas actualizadas e identificar más información sobre el conflicto.

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

Establecer información de contexto

Mediante la cláusula WITH CHANGE_TRACKING_CONTEXT, una aplicación puede almacenar la información de contexto junto con la información de cambios. Esta información se puede obtener a continuación en la columna SYS_CHANGE_CONTEXT que CHANGETABLE (CHANGES …) devuelve.

La información de contexto se suele utilizar para identificar el origen de los cambios. Si el origen del cambio se puede identificar, un almacén de datos puede utilizar esa información para evitar obtener los cambios cuando se sincronice de nuevo.

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

Asegurarse de que los resultados son coherentes y correctos

Una aplicación debe considerar el proceso de limpieza cuando valida el valor de @last_sync_version. Esto se debe a que los datos se podrían haber quitado después de llamar a CHANGE_TRACKING_MIN_VALID_VERSION(), pero antes de que se realizara la actualización.

Nota importanteImportante

Recomendamos usar el aislamiento de instantánea y realizar los cambios dentro de una transacción de instantáneas.

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

Nota

Existe la posibilidad de que la fila que se está actualizando en la transacción de instantáneas pueda haber sido actualizada en otra transacción una vez iniciada la transacción de instantáneas. En este caso, se producirá un conflicto de actualización del aislamiento de instantánea que provocará que se termine la transacción. Si esto ocurre, vuelva a intentar la actualización. Esto conducirá entonces a la detección de un conflicto del seguimiento de cambios y a que no se realicen cambios en ninguna fila.