AWS DMS: rosnące opóźnienie CDC i awaria taska replikacyjnego
Naprawa rosnącego opóźnienia CDC i awarii taska AWS DMS: diagnoza CDCLatencySource vs CDCLatencyTarget, tabele bez klucza głównego, obcięcie LOB i sizing instancji replikacyjnej.
Ten runbook opisuje rozwiązywanie problemów z taskiem AWS DMS podczas migracji bazy danych. Pełny przewodnik po samej usłudze znajdziesz w artykule AWS DMS - przewodnik po migracji baz danych. W kwestii planowania i realizacji migracji umów konsultację.
Objaw
Task DMS jest w stanie „Running”, ale nie zbliża się do końca, albo przechodzi w „Failed”/„Error”. Typowe sygnały:
# Metryki CloudWatch pokazuja rosnace opoznienie CDC (w sekundach)
aws cloudwatch get-metric-statistics \
--namespace AWS/DMS \
--metric-name CDCLatencyTarget \
--dimensions Name=ReplicationInstanceIdentifier,Value=dms-prod \
Name=ReplicationTaskIdentifier,Value=oracle-to-aurora \
--start-time $(date -u -d '1 hour ago' +%Y-%m-%dT%H:%M:%S) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%S) \
--period 60 --statistics Maximum \
--query 'Datapoints | sort_by(@, &Timestamp) | [-10:].[Timestamp,Maximum]'
# Status i statystyki tabel taska (ktore tabele sa w stanie Error)
aws dms describe-table-statistics \
--replication-task-arn arn:aws:dms:eu-west-1:123456789012:task:ORACLE2AURORA \
--query 'TableStatistics[?TableState!=`Table completed`].{schema:SchemaName, table:TableName, state:TableState, fullLoadRows:FullLoadRows}' \
--output table
# Typowe komunikaty w logach taska (CloudWatch Logs, grupa dms-tasks-*):
# "Some changes from the source database were not applied due to missing primary key"
# "LOB column data was truncated" / "Limited LOB mode"
# "Last Error ... Task error notification received from subtask"
Opóźnienie CDCLatencyTarget narasta w czasie (nie stabilizuje się), albo w statystykach tabel pojawia się stan Table error.
Przyczyna
Rosnące opóźnienie CDC i błędy taska mają zwykle jedną z czterech przyczyn:
- Instancja replikacyjna za jest mała: przy dużym wolumenie transakcji na źródle instancja nie nadąża z odczytem i aplikowaniem zmian. Reguła kciuka: ~1 vCPU na 50 GB ładowanych danych lub na 100 tabel pod CDC. Zbyt mała klasa (np. dms.t3) pod produkcyjnym obciążeniem to najczęstsza przyczyna narastającego opóźnienia.
- Tabele bez klucza głównego: CDC identyfikuje wiersze po kluczu. Tabela bez klucza głównego lub unikalnego indeksu powoduje, że operacje UPDATE/DELETE nie mają jak trafić w konkretny wiersz - task zgłasza błąd lub w skrajnym przypadku aplikuje zmiany do wszystkich pasujących wierszy.
- Obcięcie LOB (Limited LOB mode): domyślny tryb DMS ucina kolumny BLOB/CLOB/BYTEA powyżej ustalonego
LobMaxSize. To cicha utrata danych - task nie pada, ale dane docelowe są niekompletne. - Rozróżnienie CDCLatencySource vs CDCLatencyTarget: wysoki
CDCLatencySourcewskazuje problem po stronie źródła (np. brak supplemental logging w Oracle, wolny odczyt logów, LogMiner pod obciążeniem). WysokiCDCLatencyTargetprzy niskim source wskazuje wąskie gardło po stronie aplikowania zmian na celu (rozmiar instancji, indeksy, wyzwalacze).
Rozwiązanie
A) Ustal, po której stronie jest wąskie gardło (source vs target):
# Porownaj obie metryki opoznienia w tym samym oknie czasowym
for M in CDCLatencySource CDCLatencyTarget; do
echo "=== $M ==="
aws cloudwatch get-metric-statistics \
--namespace AWS/DMS --metric-name $M \
--dimensions Name=ReplicationInstanceIdentifier,Value=dms-prod \
Name=ReplicationTaskIdentifier,Value=oracle-to-aurora \
--start-time $(date -u -d '30 minutes ago' +%Y-%m-%dT%H:%M:%S) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%S) \
--period 60 --statistics Average \
--query 'Datapoints | sort_by(@, &Timestamp) | [-5:].[Timestamp,Average]'
done
# Wysoki source -> problem na zrodle (logowanie zmian).
# Wysoki target przy niskim source -> problem na celu (sizing/indeksy).
B) Wysoki CDCLatencySource - napraw logowanie zmian na źródle (Oracle):
-- Sprawdz supplemental logging (wymagane dla CDC z Oracle)
SELECT supplemental_log_data_min, supplemental_log_data_pk, supplemental_log_data_ui
FROM v$database;
-- Wlacz, jesli wylaczone
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (PRIMARY KEY, UNIQUE INDEX) COLUMNS;
-- Dla MySQL: binlog w formacie ROW; dla PostgreSQL: wal_level = logical
C) Wysoki CDCLatencyTarget - zwiększ instancję replikacyjną lub zrównoleglij:
# Powieksz klase instancji replikacyjnej (bez odtwarzania taska)
aws dms modify-replication-instance \
--replication-instance-arn arn:aws:dms:eu-west-1:123456789012:rep:DMSPROD \
--replication-instance-class dms.r5.2xlarge \
--apply-immediately
# W ustawieniach taska zwieksz rownoleglosc aplikowania (task settings JSON):
# "TargetMetadata": { "ParallelApplyThreads": 8, "ParallelApplyBufferSize": 1000 }
# oraz dla full load: "FullLoadSettings": { "MaxFullLoadSubTasks": 8 }
D) Tabele bez klucza głównego - dodaj klucz lub migruj tylko w full load:
-- Zidentyfikuj tabele bez klucza glownego na zrodle (Oracle)
SELECT t.owner, t.table_name
FROM all_tables t
WHERE NOT EXISTS (
SELECT 1 FROM all_constraints c
WHERE c.table_name = t.table_name AND c.owner = t.owner
AND c.constraint_type = 'P')
AND t.owner = 'APP_SCHEMA';
-- Dodaj klucz glowny przed migracja (preferowane) LUB
-- oznacz te tabele do migracji wylacznie w trybie Full Load (bez CDC) w table mapping.
E) Obcięcie LOB - przełącz na Full LOB lub dobierz LobMaxSize:
# W ustawieniach taska (task settings JSON) dla tabel z duzymi LOB:
# "TargetMetadata": {
# "SupportLobs": true,
# "FullLobMode": true, # pelne LOB (wolniej, ale bez obciecia)
# "LobChunkSize": 64,
# "LimitedSizeLobMode": false
# }
# LUB tryb Inline/Limited z odpowiednio dobranym LobMaxSize (KB) do najwiekszego LOB.
# Po zmianie ustawien - task wymaga zatrzymania i wznowienia
aws dms stop-replication-task --replication-task-arn arn:aws:dms:eu-west-1:123456789012:task:ORACLE2AURORA
aws dms start-replication-task --replication-task-arn arn:aws:dms:eu-west-1:123456789012:task:ORACLE2AURORA \
--start-replication-task-type resume-processing
Prewencja: monitoruj CDCLatencyTarget od pierwszego dnia migracji, nie w dniu cutoveru. Włącz zadanie Data Validation w DMS, żeby wychwycić rozbieżności danych (w tym obcięte LOB). Dla dużych baz dobierz instancję replikacyjną z zapasem i skonfiguruj alarm CloudWatch na CDCLatencyTarget powyżej progu (np. 300 s).
Walidacja
# 1. Opoznienie CDC spada i stabilizuje sie blisko zera
aws cloudwatch get-metric-statistics \
--namespace AWS/DMS --metric-name CDCLatencyTarget \
--dimensions Name=ReplicationInstanceIdentifier,Value=dms-prod \
Name=ReplicationTaskIdentifier,Value=oracle-to-aurora \
--start-time $(date -u -d '15 minutes ago' +%Y-%m-%dT%H:%M:%S) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%S) \
--period 60 --statistics Average
# Oczekiwane: trend malejacy, docelowo < 5 s
# 2. Zadna tabela nie jest w stanie bledu
aws dms describe-table-statistics \
--replication-task-arn arn:aws:dms:eu-west-1:123456789012:task:ORACLE2AURORA \
--query 'TableStatistics[?TableState==`Table error`].{schema:SchemaName, table:TableName}' \
--output table
# Oczekiwane: pusta lista
# 3. Walidacja danych (jesli wlaczona) nie zglasza rozbieznosci
aws dms describe-table-statistics \
--replication-task-arn arn:aws:dms:eu-west-1:123456789012:task:ORACLE2AURORA \
--query 'TableStatistics[].{table:TableName, validation:ValidationState, pending:ValidationPendingRecords, failed:ValidationFailedRecords}' \
--output table
# Oczekiwane: ValidationState = "Validated", failed = 0
Jeśli opóźnienie CDC jest stabilnie niskie, żadna tabela nie jest w stanie błędu, a walidacja danych przechodzi bez rozbieżności - task jest gotowy do cutoveru. Utrzymuj replikację do momentu przełączenia i monitoruj opóźnienie aż do wstrzymania zapisu na źródle.
Migracja bazy danych z DMS się przeciąga?
Umów bezpłatną 30-minutową rozmowę. Przejrzymy konfigurację DMS, dobierzemy tryb i sizing, i doprowadzimy migrację do czystego cutoveru.