AWS DMS CDC 연동 시 DB 락(Lock) 문제: 원인 분석과 실전 해결 5가지
많은 개발자분들이 AWS DMS(Database Migration Service)를 처음 도입할 때, CDC(Change Data Capture, 변경 데이터 캡처) 기능만 보고 ‘전체 마이그레이션이 끝나도 무중단으로 실시간 동기화가 되겠구나’라는 기대를 갖습니다. 하지만 막상 운영 환경에 적용하면 예상치 못한 데드락(Deadlock)과 과부하로 인해 밤새 시스템을 붙잡고 씨름하는 상황이 벌어질 수 있습니다. 특히 주문, 결제처럼 쓰기 트랜잭션이 몰리는 테이블에서는 AWS DMS CDC가 DB 락(Lock)을 유발하는 사례가 자주 보고됩니다. 이 글에서는 DMS CDC 연동 시 DB 락이 발생하는 원인과 실제 운영 환경에서 검증된 해결 방법을 단계별로 정리했습니다.
📌 이 글에서 얻을 수 있는 핵심 요약
- AWS DMS CDC가 락(Lock)을 유발하는 메커니즘과 원인 분석
- 운영 환경에서 검증된 Full Load와 CDC 동시성 문제 해결 5가지 방법
- 락 발생 시 성능 저하를 최소화하면서 복구하는 단계별 액션 플랜
- 장애를 사전에 예방하는 아키텍처 개선 및 모니터링 팁
⏱️ 예상 소요 시간: 8분 | 난이도: 중급(운영 경험자 권장)
1. 사건의 발단: CDC 태스크 시작 5분 만에 발생한 락
우리 팀은 기존에 운영 중이던 MySQL 데이터베이스의 크기가 커지면서 Aurora MySQL로의 전환을 결정했습니다. AWS DMS를 선택한 이유는 명확했습니다. Full Load(전체 복제)만 하면 서비스 점검이 필요하니, Full Load 후 CDC 단계로 전환해 무중단 목표의 마이그레이션을 수행하려는 계획이었죠. 하지만 공식 문서만 참고한 기본 설정으로 실행한 결과, 전체 데이터 복제가 성공적으로 완료되고 ‘Task is running’ 상태로 전환되는 순간 기존 서비스의 핵심 트랜잭션 테이블(주문 내역)에서 수많은 Lock Waits가 발생했습니다. 새벽 시간대였음에도 데이터베이스의 Active Session 수치가 급격히 치솟았고, 결국 서비스 타임아웃이 30초를 넘어가는 상황이 발생했습니다. 문제의 원인 중 하나는 DMS CDC가 소스 DB의 변경 위치 정보(MySQL의 binlog 좌표)를 조회하고 추적하는 방식이었습니다.
2. 락 발생의 실체: 단순히 ‘동기화 부하’의 문제가 아니다
많은 분들이 CDC를 실행할 때 ‘소스 데이터베이스에 부하를 적게 줄 것’이라고 생각하지만, 실제로는 DMS의 CDC 엔진이 소스 트랜잭션의 정합성을 확인하는 과정에서 특정 구간의 락을 대기하거나 유발할 수 있습니다. 특히 다음 세 가지 상황에서 락이 극단적으로 증가하는 것을 확인했습니다.
2.1 순간 Spike성 트랜잭션과 스냅샷 고립 수준
CDC는 시작 지점을 정확히 잡기 위해 내부적으로 소스 DB의 binlog 좌표를 조회합니다. 이때 소스 DB의 트랜잭션 고립 수준이나 복제 설정에 따라 메타데이터 락이 짧게 발생할 수 있습니다. 만약 주문과 같은 빈번한 INSERT/UPDATE가 발생하는 테이블이라면, 이 조회 과정에서 Lock Wait이 폭증할 가능성이 높습니다. 실전 팁: CDC 시작 전에 information_schema.innodb_trx를 조회해 장시간 실행 중인 트랜잭션이 없는지 확인하고, 시작 시각을 애플리케이션 피크 시간과 겹치지 않게 잡는 것이 좋습니다.
2.2 태스크 개수 및 파티션 과다 설정
AWS 콘솔에서 여러 테이블을 하나의 DMS 태스크에 포함하거나, 테이블 매핑 규칙을 과도하게 세분화하면 DMS가 테이블 접근 권한을 확인하는 과정에서 대상 테이블에 임시 락(Temporary Lock)을 걸어버리는 현상이 나타날 수 있습니다. 이는 개발 환경에서는 재현되지 않고, 동시 접속자가 많은 프로덕션 환경에서만 발생하는 경우가 많습니다. 때문에 실제 운영 환경과 유사한 조건에서 사전 테스트를 진행해야 합니다.
2.3 소스와 타겟의 트랜잭션 정합성 문제
소스 MySQL의 binlog_row_image 값이 FULL이 아닌 경우, DMS가 변경 전 이미지(Before Image)를 조회하기 위해 외래키(FK) 참조 테이블에 공유 잠금(Shared Lock)이 간헐적으로 발생할 수 있습니다. 이 현상은 DMS 로그에는 잘 나타나지 않고, DB 측의 LOCK WAIT 이벤트로 뚜렷하게 확인됩니다. 따라서 소스 DB 파라미터 그룹에서 binlog_format=ROW, binlog_row_image=FULL을 유지하는 것이 중요합니다.
| 증상 | 일반적인 예상(오해) | 실제 원인(진실) |
|---|---|---|
| Active Session 급증 | CPU 부하로 인한 성능 저하 | DMS의 긴 트랜잭션 참조로 인한 Lock Waits |
| 쓰기 지연 | 타겟 DB 인덱스 문제 | 소스 DB 내 임시 테이블 DDL 락 |
| DMS 처리량 하락 | 네트워크 대역폭 협소 | Binlog 동기화 캐시 사이즈 부족 |
3. 실전 해결 방안: CDC 락 부담을 줄이는 5가지 방법
위에서 언급한 원인을 종합해, 우리는 야간 점검과 함께 다음 5가지 단계를 순차적으로 적용했습니다. 각 단계는 독립적으로 적용할 수 있지만, 시너지를 위해 함께 적용하는 것을 권장합니다.
3.1 파라미터 그룹 조정 (소스 DB 최적화)
첫 번째로 시도한 방법은 DMS가 CDC 중 소스 테이블을 스캔할 때 락을 길게 유지하지 않도록, 소스 DB의 세션 타임아웃과 트랜잭션 고립 수준을 조정하는 것입니다. 소스가 MySQL/MariaDB라면 다음 설정을 검토해 보세요.
- transaction_isolation = READ-COMMITTED: 갭 락(Gap Lock)을 회피해 레코드 간 간섭을 줄입니다.
- binlog_format = ROW + binlog_row_image = FULL: DMS가 변경 전후 데이터를 정확히 읽을 수 있도록 보장합니다.
- innodb_lock_wait_timeout = 15: 너무 오랜 락 대기가 발생하지 않도록 타임아웃을 기본값보다 낮추되, 운영 쿼리 습관에 맞게 조정합니다.
3.2 DMS Task 설정: 매핑 규칙으로 태스크 분리
AWS 콘솔에서 전체 테이블을 하나의 태스크(Full Load + CDC)로 묶는 것은 위험합니다. 트랜잭션이 자주 발생하는 테이블(주문, 결제)과 참조 테이블(고객, 상품)을 분리해 별도의 DMS 태스크로 구성했습니다. 여기서 핵심은 테이블 매핑 시 include로 변경이 필요한 테이블만 지정하고, exclude로 로그성 대용량 테이블을 제외하면 락 경합이 현저하게 줄어든다는 점입니다.
3.3 CDC 시작 시점 조절
DMS 콘솔에서 태스크를 생성할 때 ‘Start task on creation’이나 ‘Start task immediately’ 옵션 대신 ‘Manually start’를 선택하고, 애플리케이션 부하가 가장 낮은 새벽 시간에 수동으로 시작했습니다. 이때 단순히 시작하는 것이 아니라 Start position time(시작 시각)을 변경 예정 시점 가까이로 명시해 DMS가 과도하게 오래된 로그를 읽지 않도록 했습니다. UTC 기준으로 입력해야 하므로 KST와의 시차를 반드시 확인하세요.
3.4 대상 테이블의 FK(외래키) 제약조건 일시 해제
락이 발생하는 가장 큰 원인 중 하나는 대상 Aurora MySQL에서 CDC 트랜잭션이 커밋되지 않은 상태에서 FK 제약조건을 검사하는 과정이었습니다. 검증된 팁은 마이그레이션 도중 대상 테이블의 FK 제약조건을 비활성화해 두고, CDC가 최신 데이터를 맞춘 뒤 검증 단계에서 다시 활성화하는 방법입니다. 다만 비활성화 기간 동안 데이터 정합성이 깨질 수 있으므로, 스테이징 환경에서 충분히 테스트하고 복구 검증 스크립트를 준비해야 합니다.
3.5 DMS 인스턴스 클래스 스케일업 (단기적 해결)
모든 소프트웨어적 설정을 마친 후에도 근본적인 처리량이 부족하면 락이 해제되지 않고 데이터가 밀려 커넥션 대기가 지속되는 경우가 있습니다. DMS 인스턴스 유형을 dms.c5.xlarge 이상으로 임시 업그레이드하면 CDC 파서가 소스 로그를 읽는 속도가 빨라져 락 해제가 원활해질 수 있습니다. 장애가 해소된 뒤에는 인스턴스 크기를 다시 낮추고, 이후에는 CloudWatch 알림으로 처리량을 관리하는 것이 좋습니다.
4. 락 해소 후, 안정적으로 운영하기 위한 아키텍처 개선
락 문제를 해결한 이후에도 재발 방지를 위해 최종 전환(Cutover) 직전 프로세스를 보완했습니다.
- 검증 단계 분리: DMS의 데이터 검증 기능(Data Validation)은 소스에 추가 쿼리를 보내므로, 운영 시간대에는 비활성화하고 유지보수 시간에만 검증을 실행합니다.
- 모니터링 알림 생성: CloudWatch를 활용해 DMS 메트릭 중
CDC Changes Memory Limit,CDC Memory Limit이 70%를 초과하거나, 소스 DB에서LOCK WAIT이벤트가 감지되면 알림을 수신하도록 설정합니다. - 네트워크 격리: DMS 리소스를 퍼블릭 서브넷이 아닌 프라이빗 서브넷에 배치하고 보안 그룹 접근 범위를 최소화해 불필요한 연결 요청을 차단합니다.
- 테스트 리허설: 스테이징 DB에 인위적으로 트랜잭션을 발생시켜 락이 걸리는 순간을 재현하고, 적용한 설정값이 실제로 락을 회피하는지 검증합니다.
5. 마무리: CDC 락을 넘어 안정적인 전환까지
결론적으로 AWS DMS CDC는 ‘무중단’이라는 이름의 마법이 아니라 소스 데이터베이스와의 협상입니다. 처음에 겪은 락 문제는 DMS가 불완전해서라기보다, 트랜잭션 특성을 고려하지 않은 기본 설정 그대로 운영했기 때문에 발생했습니다. 실제 장애 상황에서 혼자 해결하려고 하면 판단이 흐려지기 쉽습니다. 가장 빠른 해결은 DMS 태스크를 잠시 중지하고, 소스 DB의 관련 세션을 정리한 뒤, 이 글에서 설명한 파라미터와 태스크 설정을 적용하는 것입니다.
CDC가 정상적으로 동작하면 기존 서비스의 가용성에 큰 영향을 주지 않으면서 데이터가 목표 지점까지 동기화되는 모습을 확인할 수 있습니다. 이 경험은 최종 스위칭(Cutover)에서 최소 다운타임 목표를 달성할 수 있는 자신감이 되었습니다. AWS DMS 도입을 고려하고 있다면 사전 부하 테스트를 반드시 진행하고, 이 글에서 다룬 락 대응 지식을 기본 설정에 미리 반영해 보시기 바랍니다.