Openflow Connector for SQL Server
Openflow Connector for SQL Server (CDC) 소개
이 페이지에서는 SQL Server (CDC)용 Openflow Connector의 기본 개념, 사용 사례, 제한 사항, 그리고 동작 방식을 설명해요. Change Data Capture를 사용해 폴링 사이 중간 상태를 포함한 모든 행 수준 변경을 보존하는 점이 핵심입니다.
출처: Snowflake 문서
본문
Note
이 커넥터는 Snowflake Connector Terms에 의해 규율됩니다.
이 토픽은 SQL Server (CDC)용 Openflow Connector의 기본 개념, 작업 흐름, 그리고 제한 사항을 설명합니다.
Openflow Connector for SQL Server (CDC) 소개
SQL Server (CDC)용 Openflow Connector는 SQL Server 데이터베이스 인스턴스를 Snowflake에 연결하고 선택한 테이블의 데이터를 근-실시간 또는 일정에 따라 복제합니다. 커넥터는 SQL Server Change Data Capture(CDC)를 사용해 복제되는 테이블의 변경을 감지·적용합니다. 변경 데이터는 복제되는 테이블의 현재 상태와 함께 변경 테이블(change table)에 기록됩니다.
사용 사례
다음과 같은 목적이 있다면 이 커넥터를 사용하세요:
-
포괄적·중앙 집중식 보고를 위해 SQL Server 데이터를 Snowflake와 동기화.
-
폴링 간격 사이 중간 상태를 포함한 소스 데이터베이스의 모든 개별 행 수준 변경을 캡처.
지원되는 SQL Server 버전
다음 SQL Server 데이터베이스 버전과 플랫폼이 지원됩니다:
-
Microsoft SQL Server 2025
-
Microsoft SQL Server 2019
-
Microsoft SQL Server 2017
-
Microsoft SQL Server 2016 (SP1 이상, Enterprise / Standard / Developer 에디션)
-
Google Cloud SQL for SQL Server
Note
커넥터는 소스 데이터베이스와 테이블에서 SQL Server Change Data Capture가 활성화되어 있어야 합니다. CDC는 SQL Server Express나 Web 에디션(AWS RDS의 Web 에디션 포함)에서는 사용할 수 없습니다. SQL Server 2017 이상은 Enterprise, Standard, Developer 에디션에서 CDC를 지원합니다. SQL Server 2016에서는 Standard 에디션의 CDC가 SP1 이상을 요구하며, 2016 SP1 이전 빌드에서는 Enterprise 또는 Developer 에디션이 필요합니다.
Openflow 요구 사항
-
지속 복제 워크로드에 맞춰 런타임 크기를 선택하세요. 크기 조정 지침과 한 런타임에서 여러 커넥터를 실행하는 방법은 Runtime sizing을 참고하세요.
-
커넥터는 다중 노드 Openflow 런타임을 지원하지 않습니다. 이 커넥터의 런타임은 Min nodes와 Max nodes를
1로 설정해 구성하세요.
제한 사항
-
커넥터는 SQL Server 인증으로 사용자 이름·비밀번호만 지원합니다.
-
각 복제 테이블은 기본 키, 자격을 갖춘 고유 제약 조건, 자격을 갖춘 고유 인덱스, 또는 사용자 선언 논리 키를 가져야 합니다. 자세한 내용은 커넥터가 복제 키를 선택하는 방식을 참고하세요.
-
소스 데이터베이스 중 하나에 기본값이 있는 새
NOT NULL열이 추가되면 커넥터는 Snowflake 데이터베이스의 기존 레코드를 업데이트하지 않습니다. -
Column Filter JSON의 포함 목록에 새 열이 추가되면 커넥터는 Snowflake 데이터베이스의 기존 레코드를 업데이트하지 않습니다.
-
커넥터는 복제 중 열 추가·제거 같은 일반적인 소스 테이블 스키마 변경을 지원합니다. 전체 목록과 몇 가지 지원되지 않는 변경 유형은 Schema changes를 참고하세요.
-
커넥터는 복제 키로 사용하는 기본 키·고유 제약 조건·고유 인덱스를 드롭/수정하거나, CDC 캡처 인스턴스가 존재한 뒤 논리 키 열을 변경/드롭한 것을 런타임에 감지하지 못합니다. 그런 변경 후에는 영향받는 테이블의 복제를 다시 시작하세요: 테이블 복제 다시 시작 참고.
-
소스 테이블에 새 열이 추가되고 업데이트가 그 새로 추가된 열만 변경할 때, SQL Server Change Data Capture는 그 업데이트를 변경 테이블에 기록하지 않으므로 커넥터는 이를 개별 변경 이벤트로 복제할 수 없습니다. 이것은 SQL Server CDC의 제한 사항입니다: 테이블의 캡처 인스턴스가 이미 추적하는 열 중 적어도 하나를 업데이트가 수정할 때만 변경이 캡처됩니다. 커넥터는 새 캡처 인스턴스로 전환한 뒤에도 새 열의 최신 값을 대상 테이블에 계속 반영합니다.
-
커넥터는 트런케이트 테이블 연산을 지원하지 않습니다. 소스의
TRUNCATE문은 무시되며 그에 해당하는 행 삭제는 대상 테이블에 적용되지 않습니다.
Note
특정 테이블 열에 영향을 주는 제한 사항은 그 열들을 복제에서 제외해 우회할 수 있습니다.
작업 흐름
다음 작업 흐름은 SQL Server (CDC)용 Openflow Connector를 설정·실행하는 단계를 요약합니다:
-
SQL Server 데이터베이스 관리자가 다음 작업을 수행합니다:
-
sys.sp_cdc_enable_db로 각 데이터베이스에서 Change Data Capture를 활성화한 뒤,sys.sp_cdc_enable_table로 복제할 각 테이블의 캡처 인스턴스를 만듭니다. -
커넥터용 자격 증명을 만듭니다.
-
커넥터가 지원되는 스키마 변경 중 캡처 인스턴스를 회전시킬 수 있도록 Openflow CDC 래퍼 프로시저를 배포합니다. 권한이나 내부 정책이 배포를 막으면 래퍼 프로시저가 배포되지 않았을 때를 참고하세요.
-
(선택) SSL로 SQL Server 인스턴스에 연결하기 위한 SSL 인증서를 제공합니다.
-
Snowflake 계정 관리자가 다음 작업을 수행합니다:
-
커넥터용 서비스 사용자, 복제된 데이터를 저장할 대상 데이터베이스, 커넥터용 웨어하우스를 만듭니다.
-
커넥터를 설치합니다.
-
커넥터 흐름 정의에 필요한 파라미터를 지정합니다.
-
흐름을 실행합니다.
Openflow에서 실행될 때 커넥터는 다음을 수행합니다:
-
복제하도록 구성된 소스 테이블과 일치하는 스키마와 대상 테이블을 만듭니다.
-
테이블 복제 수명 주기에 따라 복제를 시작합니다.
자세한 내용은 테이블이 복제되는 방식을 참고하세요.
커넥터 동작 방식
다음 섹션은 복제, 파티션 테이블 스냅샷, 스키마 변경, 데이터 보존 등 다양한 시나리오에서 커넥터가 어떻게 동작하는지 설명합니다.
Change Data Capture 동작
커넥터는 SQL Server Change Data Capture(CDC)를 사용해 소스 테이블의 변경을 감지합니다. CDC는 SQL Server 트랜잭션 로그에서 행 수준 삽입·업데이트·삭제 활동을 전용 변경 테이블에 캡처합니다.
CDC는 개별 변경 하나하나를 보존하므로 커넥터는 데이터 동기화 사용 사례와 행의 모든 변경을 캡처해야 하는 감사(audit)·히스토리 사용 사례 모두에 적합합니다. 대신 Change Tracking을 사용하는 SQL Server용 Openflow Connector와의 비교는 SQL Server용 Openflow Connector 비교를 참고하세요.
데이터 복제
커넥터는 단일 SQL Server 인스턴스의 여러 SQL Server 데이터베이스에서 테이블 복제를 지원합니다. 커넥터는 서로 다른 데이터베이스의 복제 테이블을 대상 Snowflake 데이터베이스의 별도 스키마에 만듭니다.
복제 테이블은 소스 데이터베이스 이름, 소스 스키마 이름, 테이블 이름을 다음 형식으로 조합해 참조합니다:
<database_name>.<schema_name>.<table_name>
복제되는 각 소스 데이터베이스의 각 스키마에 대해 커넥터는 대상 Snowflake 데이터베이스에 별도 스키마를 만듭니다. 대상 스키마의 이름은 다음 예시처럼 밑줄 문자(_)로 구분된 소스 데이터베이스 이름과 소스 스키마 이름의 조합입니다:
<source_database_name>_<source_schema_name>
커넥터는 대상 스키마에 소스 테이블 이름과 같은 이름으로 테이블을 만듭니다:
<destination_database>.<destination_schema_name>.<source_table_name>
테이블이 복제되는 방식
커넥터는 다음 단계로 테이블을 복제합니다:
-
스키마 내부 검사(schema introspection): 커넥터가 열 이름과 타입을 포함한 소스 테이블의 열을 발견한 뒤 Snowflake와 커넥터의 제한 사항에 대해 검증합니다. 검증 실패는 이 단계를 실패시키고 주기가 완료됩니다. 이 단계가 성공적으로 완료된 뒤 커넥터는 빈 대상 테이블을 만듭니다.
-
스냅샷 로드: 커넥터가 소스 테이블의 모든 사용 가능한 데이터를 대상 테이블로 복사합니다. 이 단계가 실패하면 커넥터는 데이터 복제를 중지합니다. 성공적으로 완료되면 소스 테이블의 데이터가 대상 테이블에 있습니다. 큰 파티션 테이블을 처리하는 방법은 파티션 테이블 스냅샷을 참고하세요.
-
증분 로드: 커넥터가 CDC 변경 테이블에서 새 항목을 읽고 그 변경을 대상 테이블에 적용합니다. 이 과정은 테이블이 복제에서 제거될 때까지 계속됩니다. 이 단계에서의 실패는 문제가 해결될 때까지 소스 테이블의 복제를 중지합니다.
스냅샷 로드를 건너뛰고 증분 로드 과정을 사용하는 방법은 Incremental replication을 참고하세요.
파티션 테이블 스냅샷
스냅샷 로드 중 커넥터는 기본 키 순서로 각 소스 테이블을 페이지네이션합니다. 소스에서 물리적으로 파티션된 큰 테이블에서는, 요구된 순서로 행을 제공하는 인덱스가 없으면 이 순서가 매 배치마다 SQL Server가 전체 테이블을 정렬하게 하여 스냅샷이 매우 느려지거나 완료를 방해할 수 있습니다.
이를 피하기 위해 커넥터는 물리적으로 파티션된 테이블을 한 번에 한 파티션씩 스냅샷합니다. 단일 파티션을 읽으면 SQL Server가 정렬 없이 인덱스 순서로 행을 스트리밍할 수 있어 각 배치가 빠르게 끝납니다. 이 동작은 자동입니다: 커넥터가 파티션 테이블을 감지하며 구성 변경이 필요 없습니다. 파티션되지 않은 테이블은 영향이 없고 전체로 계속 읽힙니다. 이 파티션별 최적화는 스냅샷 단계에만 적용됩니다. 증분 로드는 CDC 변경 테이블에서 읽으므로 영향이 없습니다.
커넥터가 복제 키를 선택하는 방식
커넥터는 각 소스 테이블의 열 하나 또는 열 집합을 복제 키로 사용합니다. 복제 키는 행을 고유하게 식별하고, CDC 변경을 대상에 적용하는 MERGE 연산을 구동하며, 스냅샷 로드 중 행을 정렬합니다.
커넥터는 각 테이블에 대해 다음 순서로 복제 키를 결정합니다:
-
사용자 선언 논리 키. 커넥터의 Table Key Configuration JSON 파라미터가 테이블을 나열하면 커넥터는 그 열들을 복제 키로 사용하며, 테이블의 기본 키·고유 제약 조건·고유 인덱스를 덮어씁니다. 자세한 내용은 테이블의 논리 키 지정을 참고하세요.
-
기본 키. 테이블의 활성화된 기본 키 제약 조건의 열.
-
고유 제약 조건 또는 고유 인덱스. 테이블에 기본 키가 없으면 자격 있는 고유 제약 조건·고유 인덱스에 설명된 대로 커넥터가 자격 있는 고유 제약 조건·고유 인덱스를 찾습니다.
-
없음. 자격 있는 키가 없으면 커넥터는 테이블을 복제할 수 없습니다. 해결하려면 테이블에 기본 키를 추가하거나, 기존 제약 조건·인덱스를 자격을 갖추게 수정하거나(아래 기준 참고), 행을 고유하게 식별하는 열에 논리 키를 선언하세요.
자격 있는 고유 제약 조건·고유 인덱스
커넥터는 다음 경우에만 고유 제약 조건·고유 인덱스를 복제 키 후보로 평가합니다:
-
고유하고 기본 키가 아닙니다.
-
활성화(비활성화 아님)되었습니다.
-
표준 B-트리 인덱스입니다. 필터링된 인덱스(
WHERE절이 있는 것)는 제외됩니다. -
제약 조건·인덱스가 덮는 모든 열이
NOT NULL입니다.
Note
SQL Server text, image, varbinary(max) 열은 고유 제약 조건·고유 인덱스에 나타날 수 없으므로 복제 키 열로 절대 자격을 갖추지 못합니다.
동점 처리(Tiebreakers)
둘 이상의 후보가 자격을 갖추면 커넥터는 다음 선호도 순서로 결정적으로 하나를 선택합니다:
-
모든 후보 중 고유 제약 조건이 고유 인덱스보다 선호됩니다.
-
같은 유형의 후보 중 열 수가 가장 적은 후보가 선호됩니다.
-
열 수가 같은 후보 중 숫자 열이 가장 많은 후보가 선호됩니다. 커넥터는 다음 SQL Server 타입을 숫자로 셉니다:
INT,BIGINT,SMALLINT,TINYINT,DECIMAL,NUMERIC,MONEY,SMALLMONEY,FLOAT,REAL. -
여전히 동점이면 알파벳 순으로 가장 낮은 제약 조건·인덱스 이름의 후보가 선택됩니다.
동점 처리 결과와 무관하게 특정 열 집합을 사용하려면 논리 키로 선언하세요. 자세한 내용은 테이블의 논리 키 지정을 참고하세요.
복제 키 예시
다음 테이블에는 기본 키가 없지만 NOT NULL 열에 고유 제약 조건이 있습니다. 제약 조건이 자격을 갖추므로 커넥터는 그 제약 조건을 복제 키로 사용해 테이블을 복제합니다:
CREATE TABLE customers (
email NVARCHAR(255) NOT NULL,
name NVARCHAR(100),
created_at DATETIME2 DEFAULT SYSUTCDATETIME(),
CONSTRAINT uq_customers_email UNIQUE (email)
);
스키마 변경
증분 복제 중 커넥터는 소스 테이블 스키마 변경을 감지해, 복제를 중지하거나 테이블을 수동으로 재스냅샷할 필요 없이 SQL Server 캡처 인스턴스 회전으로 자동 적용할 수 있습니다. 지원되지 않는 변경이면 영향받는 테이블의 복제를 다시 시작해 복구하거나 변경을 적용하세요. 캡처 인스턴스를 관리하기 위해 커넥터는 설정 중 배포된 래퍼 프로시저를 사용합니다. 자세한 내용은 Openflow CDC 래퍼 프로시저 배포를 참고하세요.
지원되는 변경
커넥터는 다음 스키마 변경을 지원합니다:
-
열 추가. 커넥터가 대상 테이블에 열을 추가하고 새 행·업데이트된 행의 값을 복제합니다. 기존 행은 백필되지 않습니다. 변경 전에 존재하던 행에는 새 열이
NULL입니다. -
열 제거. 커넥터가 대상 열을
__SNOWFLAKE_DELETED접미사로 이름을 바꿔 히스토리 값이 보존되게 합니다. 자세한 내용은 제거된 열을 참고하세요. -
호환 가능한 타입 변경. 열을 같은 Snowflake 데이터 타입으로 매핑되는 소스 타입으로 변경하면(예:
INT를BIGINT로, 둘 다NUMBER로 매핑) 커넥터는 업데이트된 열 정의를 반영하는 새 캡처 인스턴스로 전환합니다. -
이전에 제거한 열 다시 추가. 커넥터는 기존 소프트 삭제 열 옆에 새 대상 열로 열을 추가합니다(예:
A와A__SNOWFLAKE_DELETED). -
숫자 정밀도 또는 배율 변경. 예:
DECIMAL(7,2)을DECIMAL(12,4)로 넓히기. 커넥터는 업데이트된 열 정의를 반영하는 새 캡처 인스턴스로 전환합니다. -
문자 열 길이 변경. 예:
VARCHAR(50)을VARCHAR(200)으로 넓히기. 커넥터는 업데이트된 열 정의를 반영하는 새 캡처 인스턴스로 전환합니다.
이전에 제거되고 소프트 삭제된 열을 다시 제거하면 소프트 삭제된 열 이름이 이미 사용 중이라 영향받는 테이블의 복제가 실패합니다.
지원되지 않는 변경
커넥터는 다음 스키마 변경을 지원하지 않습니다. 별도로 명시하지 않는 한, 다시 시작할 때까지 영향받는 테이블의 복제가 중지됩니다:
-
기본 키 정의 변경. SQL Server는 Change Data Capture가 활성화된 테이블의 기본 키 드롭·전환·기타 수정을 차단합니다. 이것은 커넥터의 제한이 아니라 SQL Server가 자체적으로 강제하는 소스 측 제한입니다: 어떤 변경이 커넥터에 도달하기 전에 소스 데이터베이스에서 문이 실패합니다. 기본 키가 없던 테이블에 기본 키를 추가해도 커넥터가 이미 사용하는 키는 새로고침되지 않습니다. 복제 키를 바꾸려면 영향받는 테이블의 복제를 다시 시작하세요. 자세한 내용은 제한 사항의 기본 키 재시작 지침을 참고하세요.
-
호환되지 않는 타입 변경. 새 소스 타입이 다른 Snowflake 데이터 타입으로 매핑될 때(예:
INT를VARCHAR로, 각각NUMBER와TEXT로 매핑). -
열 이름 변경. SQL Server는 활성 CDC 캡처 인스턴스에 속한 열의 이름 변경을 허용하지 않습니다. 이것은 커넥터의 제한이 아니라 SQL Server가 자체적으로 강제하는 소스 측 제한입니다: 이름 변경 문이 커넥터에 도달하기 전에 소스 데이터베이스에서 실패합니다.
래퍼 프로시저가 배포되지 않았을 때
커넥터는 Openflow CDC 래퍼 프로시저 배포의 dbo.sf_openflow_cdc_enable_table과 dbo.sf_openflow_cdc_disable_table을 기대합니다. 배포를 권한이나 내부 정책이 막을 때만 이것 없이 복제를 사용하세요. 그것을 정상 경로가 아닌 최후의 수단으로 취급하세요. 지원되는 스키마 변경이 발생할 때까지는 복제가 여전히 동작합니다. 그때 DBA가 해당 변경에 대한 수동 캡처 인스턴스 SQL을 실행해야 합니다.
MultiDatabaseCaptureChangeCdcSqlServer 프로세서에서 메시지가 Schema-change replication으로 시작하는 WARN 게시판을 찾으세요(Openflow 게시판 또는 런타임 로그). 게시판에는 실행할 SQL이 포함됩니다. 그 스크립트로 테이블을 차단 해제하거나, Openflow CDC 래퍼 프로시저 배포의 프로시저와 권한을 배포해 이후 스키마 변경이 수동 단계를 요구하지 않게 하세요. 수정 후 커넥터는 흐름을 다시 시작하거나 테이블을 다시 추가하지 않고 다음 실행에 계속됩니다.
스키마 전환 동작 방식
SQL Server 캡처 인스턴스는 캡처 인스턴스 생성 시 고정된 고정 열 집합에 대해 변경을 기록합니다. 소스 테이블의 스키마가 변경되면 커넥터는 같은 캡처 인스턴스를 계속 사용할 수 없으므로, 업데이트된 스키마를 반영하는 새 캡처 인스턴스로 전환합니다. 이 전환은 다음 단계로 일어납니다:
-
스키마 변경 감지. 커넥터는 폴링 메커니즘으로 DDL 변경을 감지합니다: 복제하는 테이블에 대해 SQL Server의
cdc.ddl_history테이블을 주기적으로 조회합니다. 폴링 간격은 구성 가능하며 기본값이 30초이므로, 스키마 변경은 같은 주기보다는 발생 직후에 감지됩니다. -
새 캡처 인스턴스 생성. 커넥터가 스키마 변경을 감지하면 변경 후 열 집합을 반영하는 새 캡처 인스턴스를 만듭니다. 새 캡처 인스턴스는 생성된 시점부터 변경을 기록하기 시작합니다.
-
이전 캡처 인스턴스 드레이닝. 커넥터는 스키마가 변경된 지점까지 이전 캡처 인스턴스에서 계속 읽어, 이전 스키마 하에서 커밋된 변경이 손실되지 않게 합니다. 이 변경들은 이전 열 집합으로 배출됩니다. 이전 스키마 하에서 커밋된 모든 변경이 새 스키마 하에서 기록된 변경보다 먼저 대상에 전달되므로, 대상은 항상 스키마 일관된 커밋 순서로 변경을 받습니다.
-
미니 스냅샷. 스키마가 변경된 지점과 새 캡처 인스턴스가 기록을 시작한 지점 사이에 간극이 있습니다. 이 간극을 채우기 위해 커넥터는 이전 캡처 인스턴스의 그 간극 변경을 재생하고, 새로 추가된 열이 현재 값을 지니도록 라이브 소스 테이블에 조인합니다. 이 미니 스냅샷은 전체 테이블을 재스냅샷하지 않고 대상 테이블을 새 스키마로 최신 상태로 만듭니다.
-
새 캡처 인스턴스로 전환. 미니 스냅샷이 완료되면 커넥터는 이전 캡처 인스턴스를 은퇴(드롭)시키고 새 인스턴스에서 정상 복제를 재개합니다.
이미 보낸 변경 재생
커넥터가 스키마 변경을 감지하면 이미 보낸 변경 레코드를 되감고·재생해야 할 수 있습니다. 예를 들어 새 열 감지 전에 보낸 레코드에는 그 열의 값이 없으므로 커넥터는 새 열을 채우기 위해 영향받는 행을 재생합니다. 커넥터는 복제 키로 변경을 멱등적으로 적용하므로 이 레코드들을 재생해도 대상 테이블에 중복 행이 생기지 않습니다.
스키마 전환 중 스키마 변경
이전 변경으로 커넥터가 아직 새 캡처 인스턴스로 전환하는 중에 두 번째 스키마 변경이 발생할 수 있습니다. 커넥터는 후속 변경을 감지해 최신 스키마를 반영하는 더 새로운 캡처 인스턴스를 프로비저닝하고, 그 더 새로운 인스턴스에 대해 전환을 계속하며 필요하면 되감아 영향받은 변경이 가장 최근 스키마 하에서 재생되게 합니다. 데이터가 손실되지 않으며 전환은 가장 최근 스키마에 대해 완료됩니다.
큰 값(Oversized values)
기본적으로 커넥터는 최대 16 MB까지 개별 값을 복제합니다. 더 큰 값을 만나면 관련 테이블을 영구 실패로 표시하고 복제를 중지합니다. 큰 값을 처리하는 방식을 바꾸려면(예: NULL로 대체) Oversized Value Strategy 대상 파라미터를 수정하세요.
Snowflake 계정에 ENABLE_OPENFLOW_CDC_BASED_SQLSERVER_SSV2 파라미터가 true로 설정되어 있으면 값별 한도를 16 MB에서 128 MB로 올릴 수 있습니다.
128 MB 값별 한도 활성화에 대한 자세한 내용은 큰 값 한도 증가를 참고하세요.
Always On 가용성 그룹과 소스 장애 조치(failover)
커넥터는 SQL Server Always On Availability Groups를 지원합니다. 커넥터는 복제를 다시 시작하거나 커넥터 구성에서 테이블을 제거할 필요 없이 계획·비계획 장애 조치를 견딥니다.
장애 조치 중 SQL Server가 기본 역할을 다른 복제본으로 옮기는 동안 소스 데이터베이스는 잠깐 오프라인일 수 있습니다. 소스 데이터베이스를 일시적으로 사용할 수 없으면 복제 테이블은 Table State Store에 현재 상태를 유지합니다. 커넥터는 다음 폴링 주기에 재시도하고, 데이터베이스가 다시 온라인이 되면 마지막으로 기록된 위치에서 증분 복제를 재개합니다. 일시적 연결 오류와 소스 일시적 미사용은 테이블을 FAILED로 옮기지 않습니다.
Note
이 동작은 지원되지 않는 스키마 변경이나 테이블의 변경 캡처를 영구히 중지하는 다른 소스 측 조건 같은 영구 실패와는 다릅니다. 그런 조건은 여전히 영향받는 테이블을 FAILED로 옮기며, 근본 문제를 해결하고 테이블 복제를 다시 시작할 때까지 계속됩니다.
연결 설정은 Always On Availability Groups를 참고하세요.
소스 데이터베이스 잠금 동작
스냅샷 단계 중 커넥터는 초기 전체 복사를 수행하기 위해 소스 테이블에서 직접 읽습니다. SQL Server의 기본 READ COMMITTED 격리 수준에서는 이 읽기 연산이 소스 테이블에 공유 잠금을 획득하며, 다른 데이터베이스 클라이언트가 동시에 충돌하는 잠금을 보유하면 교착 상태(deadlock)가 발생할 수 있습니다.
증분 복제 중 커넥터는 소스 테이블이 아니라 전용 CDC 변경 테이블에서 변경을 읽으므로 소스 테이블에 공유 잠금을 걸지 않고 여기 설명된 교착 상태의 대상이 아닙니다.
다른 애플리케이션이 사용하는 격리 수준에 영향을 주지 않고 스냅샷 단계의 교착 상태를 피하려면, 커넥터가 SNAPSHOT 격리 하에서 읽도록 구성하세요. SNAPSHOT 격리는 공유 잠금을 획득하는 대신 행 버전에서 읽으므로 커넥터의 스냅샷 쿼리가 소스 테이블의 동시 쓰기와 더 이상 경합하지 않습니다.
이 방식은 SNAPSHOT 격리를 커넥터 자체 세션에서만 사용 가능하게 하므로, 다른 애플리케이션이 의존하는 기본 READ COMMITTED 격리 수준을 바꾸지 않습니다. 이런 목적으로는 Read Committed Snapshot Isolation(RCSI) 사용을 피하세요. RCSI는 데이터베이스에 대한 모든 연결의 기본 격리 수준을 재정의하기 때문입니다.
커넥터의 SNAPSHOT 격리 활성화 단계는 SNAPSHOT 격리 하에서 소스 읽기를 참고하세요.
커넥터는 고객 데이터가 자동으로 삭제되지 않는 데이터 보존 철학을 따릅니다. 복제된 데이터에 대한 완전한 소유권과 제어권을 유지하며, 커넥터는 영구 제거보다 히스토리 정보를 보존합니다.
이 방식은 다음을 의미합니다:
-
소스 테이블에서 삭제된 행은 대상 테이블에서 물리적으로 제거되지 않고 소프트 삭제됩니다.
-
소스 테이블에서 제거된 열은 대상 테이블에서 드롭되지 않고 이름이 바뀝니다.
-
저널 테이블은 무기한 유지되며 자동으로 정리되지 않습니다.
대상 테이블 메타데이터 열
각 대상 테이블은 복제 정보를 추적하는 다음 메타데이터 열을 포함합니다:
| Column name | Type | Description |
|---|---|---|
| _SNOWFLAKE_INSERTED_AT | TIMESTAMP_NTZ | The timestamp when the row was originally inserted into the destination table. |
| _SNOWFLAKE_UPDATED_AT | TIMESTAMP_NTZ | The timestamp when the row was last updated in the destination table. |
| _SNOWFLAKE_DELETED | BOOLEAN | Indicates whether the row was deleted from the source table. When true, the row has been soft-deleted and no longer exists in the source. |
소프트 삭제된 행
소스 테이블에서 행이 삭제되면 커넥터는 대상 테이블에서 물리적으로 제거하지 않습니다. 대신 _SNOWFLAKE_DELETED 메타데이터 열을 true로 설정해 행이 삭제되었음을 표시합니다.
이 방식으로 다음을 할 수 있습니다:
-
감사·규정 준수를 위해 히스토리 데이터 보존.
-
필요할 때 삭제된 레코드 조회.
-
요구 사항에 따라 데이터를 언제·어떻게 영구 제거할지 결정.
활성(비삭제) 행만 조회하려면 _SNOWFLAKE_DELETED 열로 필터링하세요:
SELECT * FROM my_table WHERE _SNOWFLAKE_DELETED = FALSE;
삭제된 행을 조회하려면:
SELECT * FROM my_table WHERE _SNOWFLAKE_DELETED = TRUE;
제거된 열
소스 테이블에서 열이 제거되면 커넥터는 대상 테이블에서 해당 열을 드롭하지 않습니다. 대신 히스토리 값 보존을 위해 __SNOWFLAKE_DELETED 접미사를 붙여 열 이름을 바꿉니다.
예를 들어 소스 테이블에서 EMAIL이라는 열이 제거되면 대상 테이블에서 EMAIL__SNOWFLAKE_DELETED로 이름이 바뀝니다. 열 제거 전에 존재하던 행은 원래 값을 유지하고, 제거 후 추가된 행은 이 열에 NULL이 있습니다.
이름이 바뀐 열에서 여전히 히스토리 값을 조회할 수 있습니다:
SELECT EMAIL__SNOWFLAKE_DELETED FROM my_table;
이름이 바뀐 열
CDC(Change Data Capture) 메커니즘의 제한 때문에 커넥터는 열 이름 변경과 '열 제거 후 새 열 추가'를 구분할 수 없습니다. 결과적으로 소스 테이블에서 열 이름을 바꾸면 커넥터는 이를 두 개의 별도 연산으로 취급합니다: 원래 열 제거와 새 이름의 새 열 추가.
예를 들어 소스 테이블에서 열을 A에서 B로 이름을 바꾸면 대상 테이블에는 다음이 포함됩니다:
-
A__SNOWFLAKE_DELETED: 이름 변경 전의 값. 이름 변경 후 추가된 행은 이 열에NULL. -
B: 이름 변경 후의 값. 이름 변경 전에 존재하던 행은 이 열에NULL.
이름이 바뀐 열 조회
원래 열과 이름이 바뀐 열 둘 다에서 단일 통합 열로 데이터를 가져오려면 COALESCE 또는 CASE 표현식을 사용하세요:
SELECT
COALESCE(B, A__SNOWFLAKE_DELETED) AS A_RENAMED_TO_B
FROM my_table;
CASE 표현식을 사용해도 됩니다:
SELECT
CASE
WHEN B IS NOT NULL THEN B
ELSE A__SNOWFLAKE_DELETED
END AS A_RENAMED_TO_B
FROM my_table;
이름이 바뀐 열용 뷰 생성
대상 테이블을 수동으로 수정하는 대신, 이름이 바뀐 열을 단일 통합 열로 제시하는 뷰를 만들 수 있습니다. 이 방식은 원래 데이터를 보존하고 진행 중인 복제로 인한 잠재적 문제를 피하므로 권장됩니다.
CREATE VIEW my_table_unified AS
SELECT
*,
COALESCE(B, A__SNOWFLAKE_DELETED) AS A_RENAMED_TO_B
FROM my_table;
Important
대상 테이블 구조를 수동으로 수정하는 것(열 드롭·이름 변경 등)은 진행 중인 복제를 방해하고 데이터 불일치를 유발할 수 있으므로 권장되지 않습니다.
저널 테이블
증분 복제 중 소스 데이터베이스의 변경은 대상 테이블에 병합되기 전에 먼저 저널 테이블에 기록됩니다. 커넥터는 이 데이터가 감사·디버깅·재처리 목적으로 유용할 수 있으므로 저널 테이블에서 자동으로 제거하지 않습니다.
저널 테이블은 해당 대상 테이블과 같은 스키마에 생성되며 다음 명명 규칙을 따릅니다:
<TABLE_NAME>_JOURNAL_<timestamp>_<number>
여기서:
-
<TABLE_NAME>은 대상 테이블 이름입니다. -
<timestamp>는 Unix epoch 형식(1970년 1월 1일 이후 초)의 생성 타임스탬프로, 고유성을 보장합니다. -
<number>는 대상 테이블 스키마가 변경될 때마다(소스 테이블의 스키마 변경 또는 열 필터 수정에 의해) 1부터 증가합니다.
예를 들어 대상 테이블이 SALES.ORDERS라면 저널 테이블은 SALES.ORDERS_JOURNAL_1705320000_1 같은 이름일 수 있습니다.
Important
복제가 진행 중인 동안 저널 테이블을 드롭하지 마세요. 활성 저널 테이블을 제거하면 데이터 손실이나 복제 실패가 발생할 수 있습니다. 해당 소스 테이블이 복제에서 완전히 제거된 뒤에만 저널 테이블을 드롭하세요.
저널 테이블 스토리지 관리
오래된 저널 데이터를 제거해 스토리지 비용을 관리해야 한다면, 더 이상 복제되지 않는 테이블의 저널 테이블을 주기적으로 정리하는 Snowflake 태스크를 만들 수 있습니다.
저널 정리를 구현하기 전에 다음을 확인하세요:
-
해당 소스 테이블이 복제에서 완전히 제거되었는지.
-
감사·처리 목적으로 저널 데이터가 더 이상 필요 없는지.
자동 정리 태스크 생성·관리에 대한 정보는 태스크 소개를 참고하세요.
다음 단계
커넥터가 데이터 타입을 Snowflake 데이터 타입으로 매핑하는 방식을 이해하려면 SQL Server용 Openflow 커넥터: 데이터 매핑을 검토하세요.
커넥터를 설정하려면 SQL Server (CDC)용 Openflow Connector 설정을 검토하세요.