변경 내용 추적에서 데이터베이스에 대한 변경 내용을 처리하는 방법
변경 내용 추적을 사용하는 일부 응용 프로그램에서는 다른 데이터 저장소와 양방향 동기화를 수행합니다. 즉, SQL Server 데이터베이스에 적용된 변경 내용은 다른 데이터 저장소에서 업데이트되고 다른 저장소에서 적용된 변경 내용은 SQL Server 데이터베이스에서 업데이트됩니다.
응용 프로그램에서 다른 데이터 저장소의 변경 내용으로 로컬 데이터베이스를 업데이트하는 경우에는 다음 작업을 수행해야 합니다.
충돌을 확인합니다.
충돌은 같은 시간에 동일한 데이터가 두 데이터 저장소 모두에서 변경된 경우 발생합니다. 응용 프로그램은 충돌을 확인할 뿐만 아니라 충돌을 해결할 수 있는 정보를 가져올 수 있어야 합니다.
응용 프로그램 컨텍스트 정보를 저장합니다.
응용 프로그램은 변경 내용 추적 정보가 있는 데이터를 저장합니다. 이 정보는 로컬 데이터베이스에서 변경 내용을 가져온 경우 다른 변경 내용 추적 정보와 함께 사용됩니다. 이 컨텍스트 정보에 대한 일반적인 예는 변경 내용의 원본인 데이터 저장소에 대한 식별자입니다.
이전 작업을 수행하기 위해 동기화 응용 프로그램에서 다음 함수를 사용할 수 있습니다.
CHANGETABLE(VERSION…)
응용 프로그램에서 변경 내용을 적용할 때 이 함수를 사용하여 충돌을 확인할 수 있습니다. 이 함수는 변경 내용이 추적된 테이블의 지정된 행에 대한 최신 변경 내용 추적 정보를 가져옵니다. 이 변경 내용 추적 정보에는 행이 마지막으로 변경되었을 때의 버전이 포함되어 있습니다. 응용 프로그램에서는 이 정보를 사용하여 응용 프로그램이 마지막으로 동기화된 후 행이 변경되었는지 여부를 확인할 수 있습니다.
WITH CHANGE_TRACKING_CONTEXT
응용 프로그램에서 이 절을 사용하여 컨텍스트 정보를 저장할 수 있습니다.
충돌 확인
양방향 동기화 시나리오에서 클라이언트 응용 프로그램은 응용 프로그램이 마지막으로 변경 내용을 가져온 이후 행이 업데이트되지 않았는지 여부를 확인해야 합니다.
다음 예에서는 별도의 쿼리 없이 CHANGETABLE(VERSION …) 함수를 사용하여 가장 효율적인 방법으로 충돌을 확인하는 방법을 보여 줍니다. 이 예에서 CHANGETABLE(VERSION …)은 @product id에서 지정한 행에 대한 SYS_CHANGE_VERSION을 확인합니다. 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 절을 사용하여 컨텍스트 정보를 변경 내용 정보와 함께 저장할 수 있습니다. 이 정보는 CHANGETABLE(CHANGES …)에서 반환된 SYS_CHANGE_CONTEXT 열에서 가져올 수 있습니다.
일반적으로 컨텍스트 정보는 변경 내용의 원본을 식별하는 데 사용됩니다. 변경 내용의 원본을 식별할 수 있는 경우 이 컨텍스트 정보는 데이터 저장소에서 사용되어 데이터 저장소에서 다시 동기화할 때 변경 내용을 가져오지 않도록 할 수 있습니다.
-- 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
[!참고]
스냅숏 트랜잭션 내에서 업데이트되는 행이 스냅숏 트랜잭션이 시작된 후 다른 트랜잭션에서 업데이트되었을 수도 있습니다. 이런 경우에 스냅숏 격리 업데이트 충돌이 발생하고 해당 트랜잭션이 종료됩니다. 이러한 경우가 발생하면 업데이트를 다시 시도하십시오. 그러면 변경 내용 추적 충돌이 검색되고 행이 변경되지 않습니다.