12 분 소요

📚 MSSQL → AWS RDS 마이그레이션 시리즈 (전체 5편)

  1. 방법 비교 — 6가지 중에서 고르기
  2. Native Backup/Restore 실전 — 옵션 그룹부터 컷오버까지
  3. DMS + CDC 무중단 컷오버 — 풀로드 후 변경분 따라잡기지금 글
  4. 변경분 계속 쌓기 — NORECOVERY 체인과 CDC-only 결합
  5. 정합성 트러블슈팅 — 케이스별 8가지 함정

지난 글에서 Native Backup/Restore 로 풀카피 → 컷오버 순서를 정리했어요. 그런데 운영 DB 라 단 몇 분의 다운타임도 허용 안 되는 케이스가 있죠. 이번 글은 그런 상황에서 쓰는 AWS DMS + CDC 구성법이에요. 원본을 운영 중 그대로 두고 풀로드 → 변경분 실시간 따라잡기 → 컷오버 순서로 다운타임을 분 단위 이하로 줄이는 흐름을 정리합니다.

💡 이 글에서 다루는 것

  • CDC 가 처음이라면 — 개념 30초 + Change Tracking 과 차이 + MSSQL 2016 에디션 조건
  • 원본 MSSQL 에서 CDC 활성화 (DB 레벨 + 테이블 레벨)
  • 켠 CDC 가 진짜 변경을 잡는지 변경 테이블로 눈으로 확인
  • DMS Replication Instance / Endpoints / Task 세팅
  • Full Load + CDC 동시 모드 vs 분리 모드 차이
  • 스키마/인덱스/IDENTITY 는 DMS 가 안 가져온다는 점과 대응
  • CloudWatch 로 latency 추적해서 안전하게 컷오버하는 절차
  • 마이그레이션 끝난 뒤 CDC/DMS 정리(cleanup)



1. 큰 그림 — 무엇이 어디서 도는가

[내부망 MSSQL]
   │  (1) CDC 로 변경분 캡처 (트랜잭션 로그 기반)
   │
   ▼
[DMS Replication Instance (VPC)]
   │  (2) Full Load + 캡처된 변경분을 타깃에 적용
   │
   ▼
[AWS RDS for SQL Server]

DMS 는 Replication Instance 라는 EC2 같은 워커를 하나 띄워두고, 거기서 소스의 트랜잭션 로그 를 읽어와 타깃에 흘려줘요. 원본은 CDC 만 켜두면 되고, DMS 가 직접 원본을 폴링하면서 변경을 잡아갑니다.

💡 풀로드 + CDC 를 같은 task 에서 켜면 풀로드 진행 중에도 변경을 캐시해두고, 풀로드 끝나는 순간부터 따라잡기를 시작해요. “다운타임 거의 0” 의 핵심이에요.



2. 원본 MSSQL 준비 — CDC 활성화

DMS 가 MSSQL 의 변경분을 잡아가려면 원본에서 CDC 가 켜져 있어야 해요. SQL Server 의 CDC 는 트랜잭션 로그를 읽어서 변경을 별도 시스템 테이블에 기록하는 기능이에요.

2-1. CDC 가 뭔지부터 — 30초 개념

CDC 를 처음 만지는 분들을 위해 개념만 짧게 짚고 갈게요. CDC(Change Data Capture)는 테이블에 일어난 INSERT/UPDATE/DELETE 를 트랜잭션 로그에서 읽어다가, 별도의 변경 기록 테이블에 차곡차곡 쌓아두는 SQL Server 기본 기능이에요. 원본 테이블에 트리거를 다는 게 아니라, 어차피 기록되는 트랜잭션 로그를 한 번 더 활용하는 방식이라 원본 부하가 작아요.

CDC 를 켜면 SQL Server 가 자동으로 이런 것들을 만들어줘요.

생기는 것 역할
cdc.<schema>_<table>_CT 변경 테이블 테이블별 변경 이력이 쌓이는 곳 (예: cdc.dbo_Orders_CT)
cdc.lsn_time_mapping LSN ↔ 시각 매핑. “언제의 변경인지”를 시간으로 환산
cdc.<DB>_capture 로그를 읽어 변경 테이블에 채우는 SQL Agent 잡
cdc.<DB>_cleanup 오래된 변경 기록을 자동 삭제 (기본 3일 보존)

💡 여기서 LSN(Log Sequence Number) 하나만 알고 가면 돼요. 트랜잭션 로그의 각 변경에 매겨진 일련번호예요. DMS 든 CDC-only 시작이든 “이 LSN 이후부터 따라잡아” 라고 좌표를 찍을 때 쓰는 값이에요. 4편--cdc-start-position LSN:... 이 바로 이거예요.

⚠️ CDC ≠ Change Tracking. 이름이 비슷한 Change Tracking(CT)은 “이 row 가 바뀌었다”는 사실만 가볍게 남기고 옛 값은 안 보관해요. DMS 가 변경분을 실어 나르려면 옛 값·컬럼별 변경까지 들고 있는 CDC 가 필요해요. 둘을 헷갈려서 Change Tracking 만 켜두면 DMS 의 CDC task 가 안 돕니다.

🚨 MSSQL 2016 이면 에디션부터 확인하세요. CDC 는 원래 Enterprise 전용이었는데, SQL Server 2016 SP1 부터 Standard 에디션에서도 풀렸어요. 즉 2016 RTM(SP 미적용) Standard 에선 sp_cdc_enable_db 가 막혀요. 켜기 전에 버전·에디션을 먼저 보세요.

SELECT SERVERPROPERTY('ProductVersion') AS version,   -- 13.0.4001 이상이면 SP1+
       SERVERPROPERTY('Edition')        AS edition;

13.0.4001.0(SP1) 미만의 Standard 면 SP1 이상으로 올린 뒤에 CDC 를 켜야 해요. Enterprise/Developer 면 RTM 이라도 됩니다.

2-2. DB 레벨 CDC 켜기

USE [MyDB];
EXEC sys.sp_cdc_enable_db;

-- 확인
SELECT name, is_cdc_enabled 
FROM sys.databases 
WHERE name = 'MyDB';

is_cdc_enabled = 1 이면 OK.

2-3. 테이블 레벨 CDC 켜기

CDC 는 테이블 단위로 한 번 더 켜줘야 해요. 마이그레이션 대상 테이블 전부에 대해 돌립니다.

USE [MyDB];

EXEC sys.sp_cdc_enable_table
  @source_schema = N'dbo',
  @source_name   = N'Orders',
  @role_name     = NULL,           -- 별도 role 안 쓰면 NULL
  @supports_net_changes = 1;

테이블 많으면 동적 SQL 로 한 번에 돌려요.

DECLARE @sql NVARCHAR(MAX) = N'';
SELECT @sql = @sql + 
  N'EXEC sys.sp_cdc_enable_table @source_schema=N''' + s.name 
  + N''', @source_name=N''' + t.name 
  + N''', @role_name=NULL, @supports_net_changes=1;' + CHAR(13)
FROM sys.tables t
JOIN sys.schemas s ON t.schema_id = s.schema_id
WHERE s.name = 'dbo';

EXEC sp_executesql @sql;

2-4. SQL Server Agent 가 떠 있어야 함

CDC 캡처 잡(cdc.MyDB_capture) 은 SQL Server Agent 가 돌려요. Agent 가 죽어있으면 변경이 안 잡혀요.

EXEC msdb.dbo.sp_help_job @job_name = N'cdc.MyDB_capture';

current_execution_status1 (idle 아닌 실행 중) 또는 정상 스케줄로 도는지 확인하세요.

⚠️ RDS for SQL Server 소스 였다면 CDC 활성화 절차가 조금 달라요(rds_cdc_enable_db). 이 글은 온프레미스/EC2 소스 기준.

2-5. CDC 가 진짜 잡히는지 눈으로 확인

켜기만 하고 넘어가면 불안하죠. 실제로 변경이 잡히는지 1분이면 확인할 수 있어요. 대상 테이블에 더미 변경을 하나 주고, 변경 테이블을 들여다봅니다.

-- 1) 변경을 하나 발생시키고
UPDATE dbo.Orders SET updated_at = GETDATE() WHERE id = 1;

-- 2) 잠깐(capture 잡 주기, 보통 5초) 뒤 변경 테이블 조회
SELECT TOP 10 __$start_lsn, __$operation, *
FROM cdc.dbo_Orders_CT
ORDER BY __$start_lsn DESC;

__$operation 값의 의미만 알면 돼요.

__$operation 의미
1 DELETE
2 INSERT
3 UPDATE (이전 값)
4 UPDATE (이후 값)

행이 보이면 CDC 가 살아있는 거예요. ✅ 아무리 기다려도 안 보이면 십중팔구 SQL Server Agent 가 꺼져 있거나(앞 절) capture 잡이 멈춘 거예요.

💡 변경 테이블은 cdc.<DB>_cleanup 잡이 기본 3일(4320분) 만 보관하고 지워요. DMS 가 한참 뒤처지거나 task 를 멈춰둔 사이 보존 기간이 지나면 따라잡을 변경분이 날아가니, 따라잡기가 크게 밀릴 땐 보존 주기를 늘려두세요.

EXEC sys.sp_cdc_change_job @job_type = N'cleanup', @retention = 5760;  -- 4일(분)

2-6. CDC 를 잠깐 껐다 켰다면 — 공백(gap) 대처

실무에서 자주 나오는 상황이에요. “CDC 오버헤드가 부담돼서 잠깐 껐다가 두 시간 뒤에 다시 켰다.” 이러면 그 두 시간 동안의 변경이 어디에도 안 잡혀요. SQL Server CDC 를 sp_cdc_disable_*완전히 끄면 그 사이 트랜잭션 로그는 그냥 truncate 되고, DMS 가 나중에 읽을 변경분이 통째로 사라집니다. 다시 켜면 새 capture instance 가 새 LSN 부터 시작하므로, 공백 구간은 영영 복구되지 않아요.

대처는 “애초에 완전히 끄지 않기”“이미 공백이 생겼다면 재기준화” 두 갈래예요.

① (권장) 오버헤드가 걱정이면 끄지 말고 capture 잡만 멈추기

CDC 기능 자체는 켜둔 채 capture 잡만 멈추면, 그 사이 변경은 트랜잭션 로그에 보존됐다가(log_reuse_wait_desc = REPLICATION) 잡을 다시 켜는 순간 공백 없이 따라잡혀요. 대신 멈춘 동안 로그가 커지니 디스크만 보세요.

-- 멈추기 (오버헤드 잠깐 줄이고 싶을 때)
EXEC sys.sp_cdc_stop_job  @job_type = N'capture';
-- 두 시간 뒤 다시 켜기 → 로그에 쌓인 변경을 그대로 따라잡음(공백 없음)
EXEC sys.sp_cdc_start_job @job_type = N'capture';

또는 아예 끄는 대신 capture 잡 부하를 낮추는 방법도 있어요(폴링 간격↑, 배치 축소).

EXEC sys.sp_cdc_change_job @job_type = N'capture',
     @pollinginterval = 10,   -- 기본 5초 → 10초
     @maxtrans = 500;         -- 한 번에 처리할 트랜잭션 수 축소

② 이미 완전히 껐다 켜서 공백이 생겼다면 — 해당 테이블 재기준화

두 시간 공백은 CDC 로는 못 메꿔요. 영향받은 테이블만 풀로드 한 번 더(reload) 해서 타깃을 현재 스냅샷으로 다시 맞춘 뒤, 그 지점부터 CDC 를 재개하는 게 가장 안전해요.

  • DMS task 중지
  • 원본 CDC 재활성화 (sp_cdc_enable_table) — 새 capture instance 생성
  • DMS 콘솔의 Table statistics → 해당 테이블 Reload (영향 테이블만 풀로드 재실행)
  • reload 끝나면 CDC 재개 → 이후 변경분은 새 LSN 부터 정상 추적
  • 마지막에 5편의 행 수 · CHECKSUM_AGG 로 공백 구간 메꿔졌는지 확인

⚠️ updated_at 같은 워터마크 컬럼이 있으면 그 구간만 골라 MERGE 로 메꾸고 싶을 수 있는데, 그 방식은 DELETE 를 못 잡아요. 공백 동안 삭제된 행이 타깃에 남아버리니, 안전을 원하면 워터마크 catch-up 보다 테이블 reload 를 택하세요.



3. AWS 측 사전 세팅 — Replication Instance / Endpoints

3-1. Replication Subnet Group + Instance

aws dms create-replication-subnet-group \
  --replication-subnet-group-identifier dms-subnet-grp \
  --replication-subnet-group-description "DMS subnet group" \
  --subnet-ids subnet-aaaa subnet-bbbb

aws dms create-replication-instance \
  --replication-instance-identifier dms-mssql-mig \
  --replication-instance-class dms.r5.large \
  --allocated-storage 100 \
  --vpc-security-group-ids sg-xxxxxxxx \
  --replication-subnet-group-identifier dms-subnet-grp \
  --no-publicly-accessible \
  --multi-az

인스턴스 사이즈는 풀로드 데이터량/병렬도/CDC 부하 따라 골라요. 보통 dms.r5.large 부터 시작해서 latency 보면서 키워요.

3-2. Source / Target Endpoints

Source (내부망 MSSQL) — S2S VPN 으로 접근.

aws dms create-endpoint \
  --endpoint-identifier mssql-source \
  --endpoint-type source \
  --engine-name sqlserver \
  --server-name 10.x.x.x \
  --port 1433 \
  --database-name MyDB \
  --username dms_user \
  --password '<DMS_USER_PASSWORD>'

Target (AWS RDS for SQL Server)

aws dms create-endpoint \
  --endpoint-identifier rds-target \
  --endpoint-type target \
  --engine-name sqlserver \
  --server-name my-mssql-rds.xxxx.ap-northeast-2.rds.amazonaws.com \
  --port 1433 \
  --database-name MyDB \
  --username admin \
  --password '<RDS_ADMIN_PASSWORD>'

3-3. Connection 테스트

엔드포인트를 만들면 반드시 한 번 테스트.

aws dms test-connection \
  --replication-instance-arn arn:aws:dms:ap-northeast-2:123456789012:rep:DMS-MSSQL-MIG \
  --endpoint-arn arn:aws:dms:ap-northeast-2:123456789012:endpoint:MSSQL-SOURCE

✅ 결과가 successful 이어야 다음 단계로 갈 수 있어요. 실패 사유는 콘솔의 Last failure message 에 떨어져요.

3-4. 소스 계정 권한

dms_user 에는 최소 권한만. 흔히 깨지는 권한 세트는 다음 세 가지에요.

USE master;
GRANT VIEW SERVER STATE TO dms_user;

USE MyDB;
EXEC sp_addrolemember 'db_owner', 'dms_user';   
-- 또는 SELECT + VIEW DATABASE STATE + db_datareader 조합

DMS 가 CDC 함수(fn_cdc_get_all_changes_*) 를 호출해야 해서 단순 db_datareader 만으론 부족해요. db_owner 가 가장 깔끔하지만, 보안상 줄이고 싶다면 EXECUTE 권한을 CDC 함수에 별도 부여하는 방식이 있어요.



4. 스키마는 따로 — DMS 가 안 챙기는 것들

🚨 여기서 가장 많이 헷갈려요. DMS 는 데이터 위주 로 옮기는 서비스라, 다음을 직접 챙겨야 해요.

항목 DMS 가 옮겨주나?
테이블 구조 (CREATE TABLE) △ (기본 타입 변환만, 추천 X)
인덱스 (clustered/nonclustered)
외래키 제약 ❌ (풀로드 중 자동 disable 권장)
트리거 / 저장 프로시저 / 함수
시퀀스 / IDENTITY 시드
사용자/로그인/권한

일반적인 대응 패턴

  1. 원본에서 SqlPackage /Action:ExtractDACPAC 만들기 (스키마만, 데이터 X)
  2. 타깃 RDS 에 SqlPackage /Action:Publish 로 스키마 먼저 적용
  3. 그 다음 DMS 로 데이터만 채우기
  4. DMS 끝난 후 외래키 / 트리거 / 시퀀스 시드 보정

또는 SSMS 의 “Generate Scripts” 로 스키마 + 보조 객체 만 추출해도 OK.

💡 풀로드 중에는 타깃의 외래키와 인덱스를 잠시 끄거나 비활성화 하는 게 빨라요. Task 설정의 Target metadata 에서 BatchApplyEnabled + 인덱스/제약 처리를 조정할 수 있어요.



5. Migration Task 만들기

이제 본 task. Full Load + CDC 모드로 만들고, table mapping 으로 옮길 테이블을 지정해요.

5-1. Table mappings (table-mappings.json)

{
  "rules": [
    {
      "rule-type": "selection",
      "rule-id": "1",
      "rule-name": "select-dbo",
      "object-locator": {
        "schema-name": "dbo",
        "table-name": "%"
      },
      "rule-action": "include"
    }
  ]
}

dbo 스키마의 모든 테이블을 선택. 일부만 옮길 거면 table-name 을 구체적으로.

5-2. Task settings (task-settings.json)

{
  "TargetMetadata": {
    "BatchApplyEnabled": true,
    "ParallelLoadThreads": 8,
    "ParallelLoadBufferSize": 500
  },
  "FullLoadSettings": {
    "TargetTablePrepMode": "TRUNCATE_BEFORE_LOAD",
    "MaxFullLoadSubTasks": 8,
    "CommitRate": 10000
  },
  "Logging": {
    "EnableLogging": true,
    "LogComponents": [
      { "Id": "SOURCE_CAPTURE", "Severity": "LOGGER_SEVERITY_DEFAULT" },
      { "Id": "SOURCE_UNLOAD",  "Severity": "LOGGER_SEVERITY_DEFAULT" },
      { "Id": "TARGET_APPLY",   "Severity": "LOGGER_SEVERITY_DEFAULT" },
      { "Id": "TARGET_LOAD",    "Severity": "LOGGER_SEVERITY_DEFAULT" }
    ]
  },
  "ChangeProcessingTuning": {
    "BatchApplyPreserveTransaction": true,
    "BatchApplyTimeoutMin": 1,
    "BatchApplyTimeoutMax": 30,
    "MinTransactionSize": 1000
  }
}
항목 의미
BatchApplyEnabled 변경을 배치로 묶어 타깃에 적용. CDC 단계에서 처리량 ↑
ParallelLoadThreads 테이블당 병렬 스레드
MaxFullLoadSubTasks 동시에 풀로드 돌릴 테이블 수
TargetTablePrepMode = TRUNCATE_BEFORE_LOAD 풀로드 전 타깃 테이블 비우기. 단, 외래키 있으면 실패할 수 있어 사전 작업 필요
CommitRate 풀로드 커밋 단위. 트랜잭션 로그 부담 조절

5-3. Task 생성

aws dms create-replication-task \
  --replication-task-identifier mssql-fullload-cdc \
  --source-endpoint-arn arn:aws:dms:...:MSSQL-SOURCE \
  --target-endpoint-arn arn:aws:dms:...:RDS-TARGET \
  --replication-instance-arn arn:aws:dms:...:DMS-MSSQL-MIG \
  --migration-type full-load-and-cdc \
  --table-mappings file://table-mappings.json \
  --replication-task-settings file://task-settings.json

# 시작
aws dms start-replication-task \
  --replication-task-arn arn:aws:dms:...:task:MSSQL-FULLLOAD-CDC \
  --start-replication-task-type start-replication

💡 full-load-and-cdc 가 핵심. full-load 만이면 풀로드 끝난 시점부터의 변경이 누락돼요.



6. 진행 모니터링 — 무엇을 봐야 하는가

6-1. Task 통계

콘솔에서 Task 의 Table statistics 탭이 가장 직관적이에요. 테이블별로

  • Full load rows / Total
  • Inserts / Updates / Deletes (CDC 단계)
  • Load state (Table completed, Before load, Full load, Table error)

6-2. CloudWatch 핵심 지표

지표 의미 컷오버 기준
CDCLatencySource 소스 트랜잭션 로그 → DMS 까지 지연 (초) 1초 이내 안정
CDCLatencyTarget DMS → 타깃 반영까지 지연 (초) 1~3초 이내 안정
CDCIncomingChanges 캡처 중인 변경 수 누적 안 쌓이고 평탄
CDCChangesMemorySource 메모리에 쌓인 변경 안정적으로 낮게
CDCChangesDiskSource 디스크로 떨어진 변경 0 근처 유지

✅ 컷오버 직전 체크 — CDCLatencyTarget연속 5~10분간 1~3초 이내 유지되면 따라잡기 안정 상태로 봐도 됩니다.

⚠️ CDCLatencyTarget 이 점점 커지면 DMS 인스턴스 사양 / 타깃 디스크 IOPS / 타깃 인덱스가 병목. 이 상태로 컷오버하면 안 됩니다.



7. 컷오버 절차 — 다운타임 분 단위 이하로

여기서부터가 본 게임이에요. 절차는 한 줄도 빼먹지 마세요.

Step 1. 사전 정렬

  • CDC latency 가 안정적으로 작음 (5~10분 연속)
  • Table statistics 의 에러 0
  • 타깃에 인덱스/외래키 보조 객체 사전 생성 완료 (또는 사전 비활성)
  • 애플리케이션 측 새 접속 정보(RDS 엔드포인트) 준비 완료

Step 2. 원본 쓰기 차단

가장 안전한 방법은 애플리케이션 측에서 새 트랜잭션을 막는 거예요. DB 단에서 막으려면

-- 원본 MSSQL
ALTER DATABASE [MyDB] SET READ_ONLY WITH ROLLBACK IMMEDIATE;

또는 앱 계정의 권한을 일시적으로 회수.

Step 3. 마지막 변경분 따라잡기 대기

CDCLatencyTarget → 0 으로 수렴
CDCIncomingChanges → 0 으로 수렴

10~30초 정도면 보통 마지막 트랜잭션까지 다 따라잡아요.

Step 4. 검증

-- 양쪽 row count 비교
SELECT COUNT(*) FROM dbo.Orders;       -- 원본
SELECT COUNT(*) FROM dbo.Orders;       -- 타깃

-- 최신 데이터 비교
SELECT MAX(updated_at) FROM dbo.Orders;

핵심 테이블 몇 개만 빠르게 비교.

Step 5. 외래키/시퀀스/IDENTITY 복구

-- 외래키 다시 enable
ALTER TABLE dbo.Orders WITH CHECK CHECK CONSTRAINT ALL;

-- IDENTITY 시드 재설정 (원본의 최댓값으로)
DBCC CHECKIDENT('dbo.Orders', RESEED, <원본 MAX(id)>);

Step 6. 앱 connection string 전환

DNS 변경 or config 핫스왑. 새 쿼리는 RDS 로 흐름.

Step 7. Task 중지

aws dms stop-replication-task --replication-task-arn arn:aws:dms:...:task:MSSQL-FULLLOAD-CDC

🎉 컷오버 완료. 다운타임은 보통 1~3분 안에 끝나요.



8. 사후 정리 — 비싸게 두지 말기

DMS Replication Instance 는 시간당 요금이 꾸준히 나와요. 컷오버 끝나면 빠르게 정리하세요.

# 1. Task 삭제
aws dms delete-replication-task --replication-task-arn ...

# 2. Endpoints 삭제
aws dms delete-endpoint --endpoint-arn arn:aws:dms:...:endpoint:MSSQL-SOURCE
aws dms delete-endpoint --endpoint-arn arn:aws:dms:...:endpoint:RDS-TARGET

# 3. Replication Instance 삭제
aws dms delete-replication-instance --replication-instance-arn arn:aws:dms:...:rep:DMS-MSSQL-MIG

원본 MSSQL 의 CDC 도 더 이상 필요 없으면 끄세요. 트랜잭션 로그 보존 부담이 줄어요.

USE [MyDB];

-- 테이블별 CDC 끄기
EXEC sys.sp_cdc_disable_table 
  @source_schema = N'dbo', 
  @source_name = N'Orders', 
  @capture_instance = N'all';

-- DB 레벨 CDC 끄기
EXEC sys.sp_cdc_disable_db;



9. 자주 깨지는 함정

저도 한 번씩 다 밟아본 함정들이에요.

  • 🚨 CDC 안 켜고 task 시작full-load-and-cdcCDC source endpoint not configured 에러로 죽음
  • 🚨 SQL Server Agent 가 꺼져있음 → CDC 캡처 잡이 안 돌아 변경이 누적되다 폭주
  • 🚨 타깃에 외래키가 켜진 채 풀로드 → 부모/자식 로드 순서 때문에 실패. 풀로드 전 disable
  • 🚨 IDENTITY 시드 미보정 → 컷오버 후 새 INSERT 가 키 충돌
  • 🚨 권한 부족 (VIEW SERVER STATE, CDC 함수 EXECUTE) → CDC 단계에서 silent 하게 latency 만 늘어남
  • 🚨 CDCLatencyTarget 이 점점 커짐 → DMS 인스턴스 / 타깃 IOPS / 인덱스 병목. 이 상태로 컷오버 절대 금지
  • 🚨 트랜잭션 로그 폭증 → CDC 가 안 따라잡고 있거나, 풀백업/로그백업 주기가 너무 길어서. log_reuse_wait_desc 확인



10. Native Backup/Restore vs DMS + CDC — 다시 정리

이전 글과 함께 의사결정 표 한 장으로 정리해드릴게요.

기준 Native Backup/Restore DMS + CDC
원본 그대로 보존(인덱스/제약/IDENTITY) ⭐⭐⭐⭐⭐ ⭐⭐⭐ (수동 보정 필요)
다운타임 분~시간 단위 분 단위 이하
운영 부담/비용 낮음 (일회성) 중간 (Task 가동 시간 비용)
셋업 난이도 낮음 중간~높음
추천 시나리오 “그대로 + 짧은 유지보수 창” “절대 다운 불가 + 운영 중 이전”

저희 사내 케이스 기준으로는

  • 유지보수 창이 1~2시간 허락 → Native Backup/Restore 단독
  • 유지보수 창이 거의 없음 → Native Backup/Restore 로 풀카피 후 DMS 의 CDC-only 모드 로 변경분만 흘려 컷오버

두 번째 패턴이 사실상 베스트에요. 풀로드 비용은 백업/복원으로 절약하고, CDC 만 DMS 로 처리해서 latency 안정화 후 컷오버.

일단 오늘은 여기까지…..
다음 글에서는 이 두 번째 패턴 — 백업/복원 + CDC-only DMS 의 결합을 단계별로 풀어볼게요.


← 이전 글: (2/5) Native Backup/Restore 실전 — 옵션 그룹부터 컷오버까지다음 글 →: (4/5) 변경분 계속 쌓기 — NORECOVERY 체인과 CDC-only 결합