병합 복제의 충돌 감지 및 해결 방법
병합 복제에서는 여러 노드가 데이터를 자율적으로 변경할 수 있으므로 한 노드에서 변경한 내용이 다른 노드에서 같은 데이터에 대해 변경한 내용과 충돌하는 경우가 있습니다. 또한 병합 에이전트에서 제약 조건 위반과 같은 오류가 발생하여 특정 노드에서 변경한 내용을 다른 노드로 전파할 수 없는 경우가 있습니다. 이 항목에서는 충돌 유형, 충돌 감지 및 해결 방법, 충돌 감지 및 해결 방법에 영향을 미치는 요소에 대해 설명합니다.
충돌 감지 및 해결
병합 에이전트에서는 MSmerge_contents 시스템 테이블의 lineage 열을 사용하여 충돌을 감지합니다. 아티클에 대해 열 수준 추적이 설정된 경우 COLV1 열도 사용됩니다. 이러한 열에는 행이나 열이 삽입 또는 업데이트된 시기 및 행이나 열을 변경한 병합 복제 토폴로지의 노드에 대한 메타데이터가 들어 있습니다. 시스템 저장 프로시저 sp_showrowreplicainfo(Transact-SQL)를 사용하여 이 메타데이터를 볼 수 있습니다.
병합 에이전트에서는 동기화 중 적용될 변경 내용을 열거할 때 메타데이터를 게시자와 구독자의 각 행과 비교합니다. 병합 에이전트에서는 이 메타데이터를 사용하여 행 또는 열이 토폴로지에 있는 두 개 이상의 노드에서 변경되었는지 여부를 확인합니다. 만약 그렇다면 충돌 가능성이 있습니다. 충돌이 감지되면 병합 에이전트에서는 충돌이 발생한 아티클에 지정된 충돌 해결 프로그램을 실행하고 해결 프로그램을 사용하여 충돌 시 적용되는 내용을 확인합니다. 적용되는 행이 게시자 및 구독자에서 적용되며 무시되는 행의 데이터는 충돌 테이블에 기록됩니다.
아티클에 대해 대화형 충돌 해결 프로그램을 선택한 경우 외에는 병합 에이전트에서 충돌을 자동으로 즉시 해결합니다. 자세한 내용은 대화형 충돌 해결을 참조하십시오. 병합 복제 충돌 뷰어를 사용하여 충돌에 적용되는 행을 수동으로 변경하는 경우 병합 에이전트에서는 다음에 동기화하는 동안 적용되는 행 버전을 무시되는 서버에 적용합니다.
해결된 충돌 로깅
병합 에이전트에서는 충돌 해결 프로그램의 논리에 따라 충돌을 해결한 후 다음과 같이 충돌 데이터를 충돌 유형에 따라 기록합니다.
- UPDATE 및 INSERT 충돌의 경우 conflict_<PublicationName>_<ArticleName> 형식의 이름이 지정된 아티클의 충돌 테이블에 무시되는 행 버전을 기록합니다. 충돌 유형과 같은 일반 충돌 정보는 MSmerge_conflicts_info 테이블에 기록됩니다.
- DELETE 충돌의 경우 무시되는 행 버전을 MSmerge_conflicts_info 테이블에 기록합니다. 업데이트가 적용되고 삭제가 적용되지 않아서 무시되는 행(삭제에 해당)에 대한 데이터가 없는 경우 **conflict_<PublicationName>_<ArticleName>**에 아무 것도 기록되지 않습니다.
각 아티클의 충돌 테이블은 sp_addmergepublication의 @conflict_logging 매개 변수에 지정된 값에 따라 게시 데이터베이스나 구독 데이터베이스 중 하나 또는 양쪽 모두(기본값)에 생성됩니다. 각 충돌 테이블의 구조는 해당 아티클의 구조와 동일하며 충돌 테이블에는 origin_datasource_id 열이 추가됩니다. 병합 에이전트에서는 지정된 게시의 충돌 보존 기간보다 오래된 데이터를 충돌 테이블에서 삭제합니다. 충돌 보존 기간은 sp_addmergepublication의 @conflict_retention 매개 변수를 사용하여 지정할 수 있습니다(기본값: 14일).
복제에서는 충돌 데이터를 볼 수 있는 복제 충돌 뷰어와 저장 프로시저(sp_helpmergearticleconflicts, sp_helpmergeconflictrows 및 sp_helpmergedeleteconflictrows)를 제공합니다. 자세한 내용은 방법: 병합 게시에 대한 데이터 충돌 보기 및 해결(SQL Server Management Studio) 및 How to: View Conflict Information for Merge Publications (Replication Transact-SQL Programming)를 참조하십시오.
충돌 해결 방법에 영향을 미치는 요소
병합 에이전트가 감지된 충돌을 해결하는 방법에 영향을 미치는 두 가지 요소는 다음과 같습니다.
- 구독 유형: 클라이언트 또는 서버(구독이 끌어오기 구독인지 밀어넣기 구독인지 여부는 충돌 해결 방법에 영향을 미치지 않음)
- 사용된 충돌 추적 유형: 행 수준, 열 수준 또는 논리 레코드 수준
구독 유형
구독 생성 시 밀어넣기 구독인지 끌어오기 구독인지 여부 외에 클라이언트 구독인지 서버 구독인지 여부도 지정합니다. 구독이 생성된 후에는 구독 유형을 변경할 수 없습니다. Microsoft SQL Server 이전 버전에서는 클라이언트 구독과 서버 구독을 각각 로컬 구독과 전역 구독이라고 불렀습니다.
우선 순위 값(0.00-99.99)이 할당된 구독을 서버 구독이라고 하고, 게시자의 우선 순위 값을 사용하는 구독을 클라이언트 구독이라고 합니다. 또한 구독 유형이 서버인 구독자는 데이터를 다른 구독자로 다시 게시할 수 있습니다. 다음 표에서는 두 구독 유형의 주요 차이점과 사용 시기를 요약합니다.
유형 | 우선 순위 값 | 사용 시기 |
---|---|---|
서버 |
사용자가 우선 순위 값을 할당함 |
각각의 구독자에 서로 다른 우선 순위를 지정하려는 경우 |
클라이언트 |
우선 순위 값이 0.00이지만 동기화 이후에는 데이터 변경 내용에 게시자의 우선 순위 값이 할당됨 |
모든 구독자가 같은 우선 순위를 갖도록 하고 충돌 시 우선 적용되도록 첫 번째 구독자를 게시자와 병합하려는 경우 |
클라이언트 구독에서 행이 변경되는 경우 구독이 동기화될 때까지 변경 내용에 우선 순위가 할당되지 않습니다. 동기화 중에 구독자의 변경 내용에 게시자의 우선 순위가 할당되고 후속 동기화에 대해 이 우선 순위를 유지합니다. 즉, 게시자가 변경 작업을 수행하게 됩니다. 따라서 첫 번째 구독자가 게시자와 동기화하면 지정한 행 또는 열에 대해 다른 구독자와 후속 충돌 시 우선 적용될 수 있습니다.
서버 구독에서 행을 변경하면 구독 우선 순위는 이 변경에 대한 메타데이터에 저장됩니다. 이 우선 순위 값은 다른 구독자에서 변경 내용과 병합할 때 변경된 행과 함께 전달됩니다. 따라서 우선 순위가 높은 구독에서 변경된 내용이 우선 순위가 낮은 구독에서 나중에 변경된 내용보다 우선 적용됩니다.
구독의 명시적 우선 순위 값이 해당 게시자의 우선 순위 값보다 높을 수 없습니다. 병합 복제 토폴로지의 최상위 게시자에 대한 명시적 우선 순위 값은 항상 100.00입니다. 이 게시에 대한 모든 구독의 우선 순위 값은 이 값보다 작아야 합니다. 재게시 토폴로지에서는 다음과 같습니다.
- 구독자에서 데이터를 다시 게시할 경우 구독은 구독자의 상위 게시자보다 우선 순위 값이 낮은 서버 구독이어야 합니다.
- 구독자가 데이터를 다시 게시하지 않을 경우(구독자가 재게시 트리의 리프 수준에 있음) 구독은 클라이언트 구독이어야 합니다.
서버 구독 및 우선 순위에 대한 자세한 내용은 구독 유형 및 지정된 우선 순위에 따른 병합 충돌 해결 예제를 참조하십시오.
지연 충돌 알림
지연 충돌 알림은 충돌 우선 순위가 서로 다른 서버 구독에서 발생할 수 있습니다. 게시자와 우선 순위가 낮은 구독자 사이에서는 변경 내용이 충돌 없이 교환되지만 우선 순위가 높은 구독자와 게시자가 동기화할 때는 변경 내용이 충돌하는 다음 시나리오를 고려해 보십시오.
- 게시자와 우선 순위가 낮은 구독자(LowPrioritySub)가 여러 번의 동기화에서 충돌 없이 변경 내용을 교환합니다.
- HighPrioritySub라는 우선 순위가 높은 구독자가 일정 시간 동안 게시자와 동기화하지 않고 있다가 LowPrioritySub 구독자에서 변경한 행을 변경했습니다.
- HighPrioritySub 구독자의 우선 순위가 LowPrioritySub 구독자의 우선 순위보다 높기 때문에 HighPrioritySub 구독자가 게시자와 동기화한 후 HighPrioritySub 구독자의 변경 내용과 LowPrioritySub 구독자의 변경 내용이 충돌하면 HighPrioritySub 구독자의 변경 내용이 우선 적용됩니다. 이때 게시자에 HighPrioritySub 구독자가 변경한 내용이 포함됩니다.
- 그런 다음 LowPrioritySub 구독자는 게시자와 병합하고 HighPrioritySub 구독자와의 충돌로 인해 발생한 많은 양의 변경 내용을 다운로드합니다.
이때 우선 순위가 낮은 구독자에서 충돌 시 무시되는 동일한 행을 변경하면 문제가 발생할 수 있습니다. 이 경우 이 구독자에서 변경한 내용이 모두 손실될 수 있습니다. 이 문제가 발생하지 않도록 하려면 비즈니스 논리에서 별도의 지시가 없는 한 모든 구독자에 동일한 우선 순위를 지정해야 합니다.
추적 수준
데이터 변경 내용을 충돌로 규정할지 여부는 아티클에 대해 설정한 충돌 추적 유형인 행 수준, 열 수준 또는 논리 레코드 수준에 따라 달라집니다. 논리 레코드 수준 추적에 대한 자세한 내용은 논리적 레코드에서 충돌 감지 및 해결을 참조하십시오.
행 수준에서 충돌이 인식되면 같은 열의 변경 여부에 상관없이 이러한 행의 변경 내용을 충돌로 판단합니다. 예를 들어 게시자 행의 주소 열을 변경한 다음 같은 테이블에 있는 해당 구독자 행의 전화 번호 열을 변경합니다. 행 수준 추적의 경우 같은 행이 변경되기 때문에 충돌이 감지됩니다. 열 수준 추적의 경우 같은 행의 다른 열이 변경되기 때문에 충돌이 감지되지 않습니다.
행 수준 추적과 열 수준 추적에 대한 충돌 해결 방법은 동일합니다. 충돌 시 적용되는 데이터 변경 내용이 데이터의 전체 행을 덮어씁니다. 논리 레코드 수준 추적의 경우 아티클 속성 logical_record_level_conflict_resolution에 따라 해결 방법이 달라집니다.
일반적으로 응용 프로그램 기능에 따라 사용할 추적 옵션이 결정됩니다. 예를 들어 주소 및 전화 번호와 같이 대개 동시에 입력된 고객 데이터를 업데이트하는 경우에는 행 수준 추적을 선택해야 합니다. 이런 경우에 열 수준 추적을 선택한다면 한 곳에서는 고객 주소를 변경하고 다른 곳에서는 고객 전화 번호를 변경한 경우 충돌이 감지되지 않습니다. 즉, 동기화가 이루어질 때 데이터는 병합되고 오류는 누락됩니다. 서로 다른 사이트에서 개별 행을 업데이트하는 것이 가장 적합한 경우도 있습니다. 예를 들어 두 사이트가 소득 수준 및 신용 카드로 구매한 총 금액과 같이 고객의 유형이 다른 통계적 정보에 액세스할 수 있습니다. 이 경우 열 수준 추적을 선택하면 두 사이트는 불필요한 충돌 없이 다른 열의 통계적 데이터를 입력할 수 있습니다.
[!참고] 일반적으로 행 수준 추적의 동기화 성능이 보다 뛰어나므로 응용 프로그램에서 열 수준 추적이 필요한 경우가 아니면 행 수준 추적(기본값)을 사용하는 것이 좋습니다. 행 추적을 사용하는 경우 기본 테이블은 최대 1,024개의 열을 포함할 수 있지만 최대 246개의 열이 게시되도록 아티클에서 열을 필터링해야 합니다. 열 추적을 사용하는 경우에는 기본 테이블이 최대 246개의 열을 포함할 수 있습니다.
충돌 유형
대부분의 충돌은 한 노드의 업데이트가 다른 노드의 업데이트 또는 삭제와 충돌하는 경우처럼 업데이트와 관련된 충돌이지만 다른 충돌 유형도 있습니다. 이 섹션에서 설명하는 각 충돌 유형이 병합 프로세스의 업로드 단계나 다운로드 단계 중에 발생할 수 있습니다. 업로드 프로세스는 특정 병합 세션에서 가장 먼저 수행되는 변경 내용 조정 작업이며 병합 에이전트가 구독자에서 게시자로 변경 내용을 복제하는 단계입니다. 이 프로세스 중에 감지되는 충돌을 업로드 충돌이라고 합니다. 다운로드 프로세스는 게시자에서 구독자로 변경 내용을 이동하는 것이며 업로드 프로세스 후에 발생합니다. 이 프로세스 중에 발생하는 충돌을 다운로드 충돌이라고 합니다.
충돌 유형에 대한 자세한 내용은 MSmerge_conflicts_info(Transact-SQL), 특히 conflict_type 및 reason_code 열을 참조하십시오.
업데이트/업데이트 충돌
병합 에이전트에서는 한 노드에서 행(또는 열이나 논리 레코드)에 대해 수행한 업데이트가 다른 노드에서 동일한 행에 대해 수행한 다른 업데이트와 충돌하는 경우 업데이트/업데이트 충돌을 감지합니다. 이 경우 기본적으로 해결 프로그램에서는 적용되는 행 버전을 무시되는 노드로 보내고, 무시되는 행 버전을 아티클 충돌 테이블에 기록합니다.
업데이트/삭제 충돌
병합 에이전트에서는 한 노드에서 수행한 데이터 업데이트가 다른 노드에서 수행한 삭제와 충돌하는 경우 업데이트/삭제 충돌을 감지합니다. 이 경우 병합 에이전트에서 행은 업데이트하지만 대상에서 해당 행이 삭제되므로 이 행을 검색할 때 찾을 수 없습니다. 행을 업데이트한 노드의 변경 내용이 적용되는 경우 무시되는 노드의 삭제 내용이 제거되며 병합 에이전트에서 새로 업데이트된 행을 무시되는 노드로 보냅니다. 병합 에이전트에서는 무시되는 행 버전에 대한 정보를 MSmerge_conflicts_info 테이블에 기록합니다.
실패한 변경 충돌
병합 에이전트에서 특정 변경 내용을 적용할 수 없는 경우 이러한 충돌이 발생합니다. 일반적으로 다음 예와 같이 게시자의 제약 조건 정의와 구독자의 제약 조건 정의가 서로 다르거나 제약 조건에 NOT FOR REPLICATION(NFR) 속성을 사용하는 경우 이러한 충돌이 발생합니다.
- 구독자측 제약 조건이 NFR로 표시되어 있지 않은 경우 구독자에서 외래 키 충돌이 발생할 수 있습니다.
- 게시자 제약 조건과 구독자 제약 조건이 다르며 제약 조건이 NFR로 표시되어 있지 않은 경우 충돌이 발생할 수 있습니다.
- 뷰를 게시하지만 해당 테이블은 게시하지 않는 상태에서 구독자에서 해당 뷰를 통해 삽입하려는 경우와 같이 구독자에서 종속 개체를 사용할 수 없는 경우 충돌이 발생할 수 있습니다.
- 게시에 대한 조인 필터링 논리가 PRIMARY KEY 제약 조건과 FOREIGN KEY 제약 조건과 일치하지 않는 경우 충돌이 발생할 수 있습니다. SQL Server 관계형 엔진에서는 제약 조건을 인식하려고 하는데 병합 에이전트에서 아티클 간의 조인 필터 정의를 인식하는 경우 충돌이 발생할 수 있습니다. 병합 에이전트에서 테이블 수준 제약 조건으로 인해 대상 노드의 변경 내용을 적용할 수 없으므로 충돌이 발생합니다.
- 아티클에 대해 ID 열이 정의되어 있고 자동화된 ID 관리를 사용하지 않는 경우 고유 인덱스나 UNIQUE 제약 조건 위반 또는 기본 키 위반으로 인해 충돌이 발생할 수 있습니다. 두 구독자가 새로 삽입된 행에 대해 같은 ID 값을 사용하려고 하면 이로 인해 문제가 발생할 수 있습니다. ID 범위 관리에 대한 자세한 내용은 ID 열 복제를 참조하십시오.
- 병합 에이전트가 대상 테이블에 행을 삽입하지 못하게 하는 트리거 논리로 인한 충돌이 발생할 수 있습니다. 예를 들어 구독자에서 정의한 업데이트 트리거가 NFR로 표시되어 있지 않고 해당 논리에 ROLLBACK이 포함되어 있는 경우에 충돌이 발생할 수 있습니다. 오류가 발생하면 트리거에서는 트랜잭션 ROLLBACK을 실행하고 병합 에이전트에서는 실패한 변경 충돌을 감지합니다.
참고 항목
개념
NOT FOR REPLICATION으로 제약 조건, ID 및 트리거 제어
병합 복제 작동 방법
고급 병합 복제 충돌 감지 및 해결
데이터 재게시
관련 자료
MSmerge_conflicts_info(Transact-SQL)
MSmerge_contents(Transact-SQL)
sp_addmergepublication(Transact-SQL)
sp_helpmergearticleconflicts(Transact-SQL)
sp_helpmergeconflictrows(Transact-SQL)
sp_helpmergedeleteconflictrows(Transact-SQL)