Powrót do strony głównej

Migracja Oracle → PostgreSQL bez przestoju

Szczegółowy techniczny rozkład migracji z Oracle na PostgreSQL bez przestoju serwisu. Użycie CDC za pośrednictwem Debezium i Kafka Connect, adaptacja schematu za pomocą Liquibase, korekta kodu Java, synchronizacja sequence i realizacja krok po kroku.

Jak przenieść z Oracle na PostgreSQL bez jednej minuty przestoju
Advertisement 728x90

# Migracja z Oracle na PostgreSQL bez przestoju: analiza techniczna

Przeniesienie z Oracle na PostgreSQL bez zatrzymywania serwisu to zadanie trudne, ale wykonalne. W tym artykule omawiamy krok po kroku strategię migracji opartą na rzeczywistym projekcie z mikrousługami na Spring Boot, gdzie kluczowym wymaganiem było zerowe wpływu na użytkowników. Użycie CDC poprzez Debezium pozwoliło synchronizować dane w czasie rzeczywistym, unikając przestojów i minimalizując ryzyka.

Przygotowanie: analiza struktury i danych

Pierwszy etap to głęboki audyt istniejącej bazy danych. Należy zrozumieć rozmiar danych, rozkład typów pól, obecność nieaktualnych rekordów oraz specyficznych konstrukcji Oracle, które nie mają bezpośrednich odpowiedników w PostgreSQL. Oczyszczenie nieaktualnych danych zmniejsza objętość migracji i przyspiesza proces.

Kluczowy aspekt to zgodność typów danych. Na przykład:

Google AdInline article slot
  • NUMBER(1,0)BOOLEAN
  • VARCHAR2TEXT lub VARCHAR
  • DATETIMESTAMP WITHOUT TIME ZONE
  • CLOBTEXT

Do analizy użyto zapytania SQL:

select distinct DATA_TYPE
from ALL_TAB_COLUMNS
where owner = 'schemat'
order by DATA_TYPE

Na podstawie wyników przygotowano tabelę mapowania typów, która stała się podstawą wszystkich dalszych transformacji. Ważne jest też uwzględnienie różnic w obsłudze NULL i pustych ciągów: w Oracle pusty ciąg jest traktowany jako NULL, w PostgreSQL — nie. To wymaga dostosowania logiki biznesowej i zapytań.

Dostosowanie schematu i Liquibase

Prosta zmiana sterownika bazy danych doprowadzi do błędów. Skrypty migracyjne muszą być dostosowane do PostgreSQL. W tym celu:

Google AdInline article slot
  • Operacje DDL i DML rozdzielono za pomocą kontekstów Liquibase — DML tymczasowo wyłączono.
  • Skrypty testowano iteracyjnie: po każdej zmianie uruchamiano changelog, czyszczono i przeprowadzano smoke-testy.
  • Sprawdzano poprawność preconditions oraz spójność schematu z Oracle.

Szczególną uwagę zwrócono na sequence. Bez ich synchronizacji nowe ID mogą kolidować z danymi historycznymi. Rozwiązanie:

  • Przy starcie aplikacji sprawdzane jest aktualne wartość sequence w PostgreSQL.
  • Jeśli jest mniejsze niż w Oracle — następuje przesunięcie z zapasem.
  • Logika jest idempotentna: wielokrotne uruchomienia nie powodują błędów.

W rezultacie docelowy schemat PostgreSQL został zebrany w jednym pull request, gotowy do załadowania danych.

Poprawki w kodzie aplikacji

Po udanym uruchomieniu aplikacji na pustym PostgreSQL ujawniają się błędy na poziomie kodu Java. Główne zmiany:

Google AdInline article slot
  • Zamiana adnotacji @Lob na @Column(columnDefinition = "text").
  • Obsługa NULL w natywnych zapytaniach SQL, zwłaszcza w konstrukcjach IN (...).
  • Przejście z numerycznych flag (0/1) na boolean.
  • Dostosowanie logiki porównywania ciągów z uwzględnieniem różnic Oracle/PostgreSQL.
  • Przepisanie natywnych zapytań z uwzględnieniem dialektu PostgreSQL.

Testowanie odbywało się na poziomie testów jednostkowych i integracyjnych. Szczególną uwagę zwrócono na przypadki brzegowe: puste ciągi, wartości NULL, duże pola tekstowe.

Implementacja CDC poprzez Debezium i Kafka Connect

Wybrano klasyczny stos: Debezium + Kafka Connect. Architektura:

  • Source-konnektor (Debezium Oracle) odczytuje redo log i generuje zdarzenia CDC.
  • Zdarzenia trafiają do Kafka (jeden topik na tabelę).
  • Sink-konnektor (JDBC Sink) stosuje zmiany w PostgreSQL w tej samej kolejności.

Etapy konfiguracji:

  • Initial Snapshot — pełne skopiowanie danych na moment startu.
  • Streaming Changes — ciągła replikacja INSERT/UPDATE/DELETE z redo log.
  • Order Preservation — gwarancja kolejności zmian dzięki LogMiner.

Użyte obrazy:

  • quay.io/debezium/kafka:3.0
  • quay.io/debezium/zookeeper:3.0
  • quay.io/debezium/connect:3.0
  • provectuslabs/kafka-ui:0.7.2 (do monitorowania)

Konfiguracja odbywa się poprzez REST API za pomocą curl. Interfejs Debezium w czasie migracji był niestabilny, dlatego konfiguracje przekazywano ręcznie w formacie JSON.

Przykładowa konfiguracja source-konnektora:

{
  "name": "oracle-connector",
  "config": {
    "connector.class": "io.debezium.connector.oracle.OracleConnector",
    "database.hostname": "oracle-host",
    "database.port": "1521",
    "database.user": "user",
    "database.password": "password",
    "database.dbname": "ORCLCDB",
    "database.server.name": "server1",
    "table.include.list": "schema.table1,schema.table2",
    "database.history.kafka.bootstrap.servers": "kafka:9092",
    "database.history.kafka.topic": "schema-changes"
  }
}

Przykładowa konfiguracja sink-konnektora:

{
  "name": "postgres-sink",
  "config": {
    "connector.class": "io.confluent.connect.jdbc.JdbcSinkConnector",
    "connection.url": "jdbc:postgresql://postgres:5432/db",
    "connection.user": "user",
    "connection.password": "password",
    "topics": "server1.schema.table1,server1.schema.table2",
    "auto.create": "false",
    "auto.evolve": "false",
    "insert.mode": "upsert",
    "pk.mode": "record_key",
    "pk.fields": "id"
  }
}

Niektóre tabele (np. z kluczami kompozytowymi) wymagają oddzielnej konfiguracji. Testowanie każdego konektora odbywa się izolowanie.

Ostateczne przełączenie i kontrola jakości

Po zakończeniu initial snapshot i ustabilizowaniu streamingu:

  • Uruchamiane są instancje testowe serwisów podłączone do PostgreSQL.
  • Przeprowadzane jest testowanie end-to-end: API, UI, procesy tła.
  • Wykonywane jest testowanie obciążeniowe na danych zbliżonych do produkcyjnych.
  • W momencie minimalnego obciążenia — przełączenie DNS lub tras ingress na nowe instancje.
  • Monitorowanie logów, metryk i alertów przez 24–48 godzin.

Rollback przewidziano tylko do momentu przełączenia. Potem system działa wyłącznie na PostgreSQL. Kopie zapasowe Oracle zachowano na wypadek awaryjnego odzyskiwania danych.

Co ważne

  • Brak uniwersalnego rozwiązania — każdy projekt wymaga indywidualnego dostosowania.
  • CDC bez podwójnego zapisu — akceptowalny kompromis przy dopuszczalnym opóźnieniu rzędu kilku sekund.
  • Synchronizacja sequence — obowiązkowa dla uniknięcia konfliktów ID.
  • Testowanie na każdym etapie — klucz do stabilnej migracji.
  • Debezium + Kafka Connect — elastyczny i niezawodny stos do migracji online.

Migracja trwała 18 godzin łącznie z przygotowaniami, ale faktyczny przestój dla użytkowników wyniósł 0 sekund. Projekt działa na PostgreSQL od ponad roku bez regresji.

— Editorial Team

Advertisement 728x90

Czytaj dalej