En resumen Debezium lee los registros de rehacer de Oracle a través de LogMiner, publica cada cambio como un evento de Kafka y un conector JDBC de destino aplica esos eventos a PostgreSQL en tiempo real.
El resultado es un pipeline de replicación transparente y reproducible que puedes ejecutar durante semanas antes de la migración, útil para cualquier migración de Oracle a PostgreSQL que requiera tiempo de inactividad cero o cercano a cero.
Esta publicación repasa una configuración de extremo a extremo que funciona, en servidores Oracle y PostgreSQL reales, con un esquema bancario autónomo que puede copiar y reproducir.
La mayoría de los proyectos de migración de Oracle a PostgreSQL fallan en el corte, no en la conversión del esquema.
El trabajo de esquema es difícil pero acotado: dedicas unas semanas a él, corriges lo que la herramienta de conversión no puede traducir y sigues adelante.
La transición está abierta.
Tienes una base de datos Oracle en producción que procesa miles de transacciones por segundo.
Necesita cambiar la aplicación a PostgreSQL sin perder ni una sola fila y, idealmente, sin una ventana de inactividad de varias horas.
Una migración basada en instantáneas por sí sola —volcar, restaurar, redirigir— no resuelve esto.
En el momento en que tomas la instantánea, cada nuevo INSERT, UPDATE y DELETE en Oracle es invisible para PostgreSQL.
Necesitas una herramienta que capture los cambios continuos de Oracle y los aplique a PostgreSQL de forma continua.
Debezium es el estándar de código abierto para esa tarea.
Índice
Lo que hace Debezium
Debezium es un framework de captura de datos de cambio (CDC) construido sobre Kafka Connect.
Para Oracle, utiliza el adaptador LogMiner, una característica integrada de Oracle que lee los registros de rehacer y expone cada cambio confirmado como una transmisión estructurada.
Debezium consulta LogMiner, convierte cada cambio de fila en un evento de Kafka y publica el evento en un tema de Kafka.
Un segundo conector — el sink JDBC de Debezium — se suscribe a esos temas y aplica los cambios a una base de datos de destino.
Para la replicación de Oracle a PostgreSQL, el pipeline es el siguiente:
Oracle (LogMiner) → Debezium fuente → Kafka → Debezium JDBC sink → PostgreSQLAmbos conectores se ejecutan dentro de un único proceso de Debezium Connect.
Kafka mantiene eventos en temas con nombres que corresponden a cada tabla de Oracle.
Puedes detener el "sink" y dejar que los eventos se acumulen en Kafka.
Puedes reproducir eventos desde un desplazamiento específico.
Puedes ejecutar dos "sinks" en paralelo: uno a PostgreSQL y otro a un entorno de staging para pruebas.
Esto es lo que hace que Debezium sea útil para el trabajo de migración: puedes ver exactamente lo que está sucediendo en cada etapa y puedes intervenir en cualquiera de ellas.
El medioambiente
Tres VMs en la misma red.
srv1se ejecuta Oracle 19c Enterprise Edition con un CDB llamadoORADBy una base de datos conectablepdb1.srvdebezium(192.168.0.230) ejecuta Ubuntu 24.04 con Docker, alojando el broker de Kafka y el contenedor Debezium Connect.srv2(192.168.0.181) ejecuta PostgreSQL 18 del repositorio oficial PGDG, alojando la base de datos de destinobankingdb.
La canalización replica un esquema bancario pequeño de Oracle a PostgreSQL: cinco tablas (ramas, empleados, clientes, cuentas, transacciones) con relaciones de clave foránea, tipos de datos mixtos y 18 filas de ejemplo.
El DDL completo y los datos de ejemplo se encuentran a continuación: copie y pegue reproducible desde una instalación limpia de Oracle.
Paso 1 — Preparar la fuente de Oracle
LogMiner necesita tres cosas activadas antes de que Debezium pueda leerlo.
Modo archivelog.
Sin él, Oracle sobrescribe los registros de rehacer antiguos una vez que ya no son necesarios para la recuperación de instancias.
LogMiner los necesita en disco para leerlos.
Cambiar al modo archivelog requiere un reinicio de la instancia.
-- On srv1 as SYSDBA
SHUTDOWN IMMEDIATE;
STARTUP MOUNT;
ALTER DATABASE ARCHIVELOG;
ALTER DATABASE OPEN;
ALTER PLUGGABLE DATABASE pdb1 OPEN;
Registro adicional.
Por defecto, Oracle escribe solo las columnas modificadas en el registro de rehacer.
Debezium necesita imágenes completas de fila para poblar antes campo en eventos de actualización.
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA;
ALTER DATABASE ADD SUPPLEMENTAL LOG DATA (ALL) COLUMNS;
Capturar usuario.
Debezium se conecta como un usuario común (el C## (el prefijo es obligatorio en una base de datos multiinquilina) con acceso de lectura al diccionario de datos y a las vistas de LogMiner.
Aplica todas las subvenciones; Debezium fallará al iniciarse si falta alguna.
-- On srv1, as SYSDBA, connected to the CDB root
CREATE USER C##DBZUSER IDENTIFIED BY dbz
DEFAULT TABLESPACE users
QUOTA UNLIMITED ON users
CONTAINER=ALL;
-- Session grants
GRANT CREATE SESSION TO C##DBZUSER CONTAINER=ALL;
GRANT SET CONTAINER TO C##DBZUSER CONTAINER=ALL;
-- LogMiner privilege — required to start and use LogMiner sessions
GRANT LOGMINING TO C##DBZUSER CONTAINER=ALL;
-- Transaction and dictionary access
GRANT SELECT ANY TRANSACTION TO C##DBZUSER CONTAINER=ALL;
GRANT SELECT ANY DICTIONARY TO C##DBZUSER CONTAINER=ALL;
GRANT SELECT_CATALOG_ROLE TO C##DBZUSER CONTAINER=ALL;
GRANT EXECUTE_CATALOG_ROLE TO C##DBZUSER CONTAINER=ALL;
-- Flashback and table access — needed for the initial snapshot
GRANT FLASHBACK ANY TABLE TO C##DBZUSER CONTAINER=ALL;
GRANT SELECT ANY TABLE TO C##DBZUSER CONTAINER=ALL;
-- Object creation — Debezium creates internal tracking objects in its own schema
GRANT CREATE TABLE TO C##DBZUSER CONTAINER=ALL;
GRANT LOCK ANY TABLE TO C##DBZUSER CONTAINER=ALL;
GRANT CREATE SEQUENCE TO C##DBZUSER CONTAINER=ALL;
-- LogMiner package execution
GRANT EXECUTE ON DBMS_LOGMNR TO C##DBZUSER CONTAINER=ALL;
GRANT EXECUTE ON DBMS_LOGMNR_D TO C##DBZUSER CONTAINER=ALL;
-- V$ views — Debezium queries these to track log position, archive status, and transactions
GRANT SELECT ON V_$DATABASE TO C##DBZUSER CONTAINER=ALL;
GRANT SELECT ON V_$LOG TO C##DBZUSER CONTAINER=ALL;
GRANT SELECT ON V_$LOG_HISTORY TO C##DBZUSER CONTAINER=ALL;
GRANT SELECT ON V_$LOGFILE TO C##DBZUSER CONTAINER=ALL;
GRANT SELECT ON V_$ARCHIVED_LOG TO C##DBZUSER CONTAINER=ALL;
GRANT SELECT ON V_$ARCHIVE_DEST_STATUS TO C##DBZUSER CONTAINER=ALL;
GRANT SELECT ON V_$LOGMNR_LOGS TO C##DBZUSER CONTAINER=ALL;
GRANT SELECT ON V_$LOGMNR_CONTENTS TO C##DBZUSER CONTAINER=ALL;
GRANT SELECT ON V_$LOGMNR_PARAMETERS TO C##DBZUSER CONTAINER=ALL;
GRANT SELECT ON V_$TRANSACTION TO C##DBZUSER CONTAINER=ALL;
GRANT SELECT ON V_$MYSTAT TO C##DBZUSER CONTAINER=ALL;
GRANT SELECT ON V_$STATNAME TO C##DBZUSER CONTAINER=ALL;
No acortes esto con OTORGAR DBA — las concesiones explícitas son auditables, reversibles y coinciden exactamente con la documentación de Debezium.
Paso 2 — Cree el esquema BANKING
El esquema a continuación es lo suficientemente pequeño como para pegarlo en 30 segundos y lo suficientemente variado como para ejercitar el comportamiento del tipo de datos que Debezium acierta y falla.
-- On srv1, connected to pdb1 as a privileged user
CREATE USER banking IDENTIFIED BY banking
DEFAULT TABLESPACE users
TEMPORARY TABLESPACE temp;
GRANT CONNECT, RESOURCE, CREATE VIEW TO banking;
ALTER USER banking QUOTA UNLIMITED ON users;
Conectar como banca y crea las cinco tablas:
CREATE TABLE branches (
branch_id NUMBER(6) PRIMARY KEY,
branch_name VARCHAR2(100) NOT NULL,
city VARCHAR2(50),
country VARCHAR2(50),
opened_date DATE
);
CREATE TABLE employees (
employee_id NUMBER(6) PRIMARY KEY,
branch_id NUMBER(6) NOT NULL,
full_name VARCHAR2(100) NOT NULL,
role VARCHAR2(50),
hire_date DATE,
CONSTRAINT fk_emp_branch FOREIGN KEY (branch_id) REFERENCES branches(branch_id)
);
CREATE TABLE customers (
customer_id NUMBER(8) PRIMARY KEY,
full_name VARCHAR2(100) NOT NULL,
email VARCHAR2(100),
country VARCHAR2(50),
created_at TIMESTAMP DEFAULT SYSTIMESTAMP
);
CREATE TABLE accounts (
account_id NUMBER(10) PRIMARY KEY,
customer_id NUMBER(8) NOT NULL,
branch_id NUMBER(6) NOT NULL,
account_type VARCHAR2(20),
balance NUMBER(15,2) DEFAULT 0,
opened_at TIMESTAMP DEFAULT SYSTIMESTAMP,
CONSTRAINT fk_acc_customer FOREIGN KEY (customer_id) REFERENCES customers(customer_id),
CONSTRAINT fk_acc_branch FOREIGN KEY (branch_id) REFERENCES branches(branch_id)
);
CREATE TABLE transactions (
txn_id NUMBER(12) PRIMARY KEY,
account_id NUMBER(10) NOT NULL,
employee_id NUMBER(6),
txn_type VARCHAR2(20),
amount NUMBER(15,2) NOT NULL,
txn_date TIMESTAMP DEFAULT SYSTIMESTAMP,
description VARCHAR2(200),
CONSTRAINT fk_txn_account FOREIGN KEY (account_id) REFERENCES accounts(account_id),
CONSTRAINT fk_txn_employee FOREIGN KEY (employee_id) REFERENCES employees(employee_id)
);
Inserte un conjunto de datos representativo pequeño — tres sucursales, cuatro empleados, tres clientes, cuatro cuentas, cuatro transacciones:
-- BRANCHES
INSERT INTO branches VALUES (1, 'Madrid Centro', 'Madrid', 'Spain', DATE '2010-03-15');
INSERT INTO branches VALUES (2, 'Barcelona Diagonal', 'Barcelona', 'Spain', DATE '2012-06-01');
INSERT INTO branches VALUES (3, 'Lisbon Avenida', 'Lisbon', 'Portugal', DATE '2015-09-10');
-- EMPLOYEES
INSERT INTO employees VALUES (101, 1, 'Maria Lopez', 'Branch Manager', DATE '2015-01-15');
INSERT INTO employees VALUES (102, 1, 'Carlos Diaz', 'Teller', DATE '2018-03-22');
INSERT INTO employees VALUES (103, 2, 'Anna Pereira', 'Branch Manager', DATE '2016-07-01');
INSERT INTO employees VALUES (104, 3, 'Pedro Santos', 'Account Officer', DATE '2020-11-05');
-- CUSTOMERS
INSERT INTO customers VALUES (1001, 'John Smith', 'john@example.com', 'UK', SYSTIMESTAMP);
INSERT INTO customers VALUES (1002, 'Hans Mueller', 'hans@example.com', 'Germany', SYSTIMESTAMP);
INSERT INTO customers VALUES (1003, 'Sophie Dubois', 'sophie@example.com', 'France', SYSTIMESTAMP);
-- ACCOUNTS
INSERT INTO accounts VALUES (10001, 1001, 1, 'CHECKING', 5000.00, SYSTIMESTAMP);
INSERT INTO accounts VALUES (10002, 1001, 1, 'SAVINGS', 25000.00, SYSTIMESTAMP);
INSERT INTO accounts VALUES (10003, 1002, 2, 'CHECKING', 12000.00, SYSTIMESTAMP);
INSERT INTO accounts VALUES (10004, 1003, 3, 'CHECKING', 8500.00, SYSTIMESTAMP);
-- TRANSACTIONS
INSERT INTO transactions VALUES (100001, 10001, 102, 'DEPOSIT', 1500.00, SYSTIMESTAMP, 'Salary deposit');
INSERT INTO transactions VALUES (100002, 10001, 102, 'WITHDRAWAL', 200.00, SYSTIMESTAMP, 'ATM withdrawal');
INSERT INTO transactions VALUES (100003, 10003, 103, 'DEPOSIT', 3000.00, SYSTIMESTAMP, 'Cash deposit');
INSERT INTO transactions VALUES (100004, 10004, 104, 'TRANSFER', 500.00, SYSTIMESTAMP, 'Transfer to savings');
COMMIT;
Dieciocho filas en total, todas las claves foráneas satisfechas.
Este es el estado fuente que Debezium capturará.
Paso 3: Iniciar Kafka y Kafka Connect
En srvdebezium, crea una red de Docker e inicia Kafka en modo detached para que el broker sobreviva al cierre de la terminal.
docker network create debezium-net
docker run -d --name kafka --hostname kafka --network debezium-net \
-p 9092:9092 \
-e CLUSTER_ID=$(docker run --rm quay.io/debezium/kafka:3.5 /kafka/bin/kafka-storage.sh random-uuid) \
-e NODE_ID=1 -e NODE_ROLE=combined \
-e KAFKA_CONTROLLER_QUORUM_VOTERS=1@kafka:9093 \
-e KAFKA_LISTENERS=PLAINTEXT://0.0.0.0:9092,CONTROLLER://0.0.0.0:9093 \
-e KAFKA_ADVERTISED_LISTENERS=PLAINTEXT://kafka:9092 \
quay.io/debezium/kafka:3.5
El conector Debezium para Oracle se envía sin el controlador JDBC de Oracle por motivos de licencia.
Descargar ojdbc11.jar desde Maven Central y montarlo en Connect al iniciar:
mkdir -p /home/fernando/oracle-jdbc
curl -L \
https://repo1.maven.org/maven2/com/oracle/database/jdbc/ojdbc11/21.9.0.0/ojdbc11-21.9.0.0.jar \
-o /home/fernando/oracle-jdbc/ojdbc11.jar
docker run -d --name connect --network debezium-net \
-p 8083:8083 \
-e BOOTSTRAP_SERVERS=kafka:9092 \
-e GROUP_ID=1 \
-e CONFIG_STORAGE_TOPIC=my_connect_configs \
-e OFFSET_STORAGE_TOPIC=my_connect_offsets \
-e STATUS_STORAGE_TOPIC=my_connect_statuses \
-v /home/fernando/oracle-jdbc/ojdbc11.jar:/kafka/connect/debezium-connector-oracle/ojdbc11.jar \
quay.io/debezium/connect:3.5
Utilice -d (desprendido).
Sin él, cerrar la terminal detiene el contenedor y detiene su pipeline de replicación.
Si está planificando una migración de Oracle a PostgreSQL y desea una segunda opinión sobre el diseño del corte, Ofrezco una evaluación de migración de tarifa fija →
Paso 4: Registrar el conector de origen Oracle
La configuración del conector le indica a Debezium qué base de datos leer, qué esquema capturar y dónde almacenar su historial de esquemas interno.
curl -i -X POST -H "Content-Type:application/json" \
http://localhost:8083/connectors/ -d '{
"name": "oracle-connector",
"config": {
"connector.class": "io.debezium.connector.oracle.OracleConnector",
"tasks.max": "1",
"database.hostname": "192.168.0.180",
"database.port": "1521",
"database.user": "C##DBZUSER",
"database.password": "dbz",
"database.dbname": "ORADB",
"database.pdb.name": "pdb1",
"topic.prefix": "oracle",
"schema.include.list": "BANKING",
"schema.history.internal.kafka.bootstrap.servers": "kafka:9092",
"schema.history.internal.kafka.topic": "schemahistory.oracle",
"decimal.handling.mode": "precise",
"datatype.propagate.source.type": "VARCHAR2,NUMBER,CHAR,NCHAR,NVARCHAR2"
}
}'
Cuatro ajustes que vale la pena entender:
schema.include.list: "BANCA"captura todas las tablas en el esquema BANKING.
Notabla.incluir.listase configura, por lo que cuando aparece una nueva tabla en BANKING, Debezium la detecta automáticamente; verás esto en el Paso 7.tema.prefijo: "oracle"controla el nombre del tema de Kafka.
Eventos paraBANCA.TRANSACCIONESaterrizar enoracle.BANCARIO.TRANSACCIONES.
El nombre de la PDB no aparece en el nombre del tema, aunquenombre.de.la.base.de.datosse establece; se usa para filtrar únicamente.decimal.handling.mode: "precise"hace OracleNÚMEROlos valores llegan como JavaBigDecimalen los eventos de Kafka, preservando la precisión y la escala. El sink JDBC usa esto para crearnumérico(p,s),entero largoyenterocolumnas en PostgreSQL.datatype.propagate.source.type: "VARCHAR2,NUMBER,CHAR,NCHAR,NVARCHAR2"incrusta la declaración de columna original de Oracle en el esquema de cada evento como metadatos. Sin ella, el sink solo ve el tipo JDBC.CADENApara cada columna — y creatextopara todo, incluidas las columnas numéricas.
El conector inicia inmediatamente una fase de instantánea: escanea cada tabla capturada, publica cada fila existente como un evento con tipo de operación r (lee) y luego cambia al modo de transmisión donde sigue el registro de rehacer.
Puedes ver el progreso con docker logs -f connect.
Paso 5 — Ver eventos de los CDC en vivo
Abre una segunda terminal en srvdebezium y iniciar un consumidor de consola de Kafka para observar los eventos a medida que llegan.
Tubería a través de grep para extraer solo los campos significativos — el sobre JSON completo está dominado por la definición del esquema, lo cual está bien para el procesamiento pero es ilegible en pantalla.
docker run -it --rm --name watcher --network debezium-net \
--entrypoint /kafka/bin/kafka-console-consumer.sh \
quay.io/debezium/kafka:3.5 \
--bootstrap-server kafka:9092 \
--topic oracle.BANKING.TRANSACTIONS \
--from-beginning 2>/dev/null \
| grep -oE '"(op|TXN_ID|TXN_TYPE|AMOUNT|DESCRIPTION)":"[^"]*"'
Aparecen inmediatamente cuatro eventos de instantánea, uno por cada transacción existente, cada uno con "op":"r".
Ahora genera un cambio en vivo en Oracle:
INSERT INTO transactions VALUES (100005, 10002, 102, 'DEPOSIT', 5000.00, SYSTIMESTAMP, 'Bonus deposit');
COMMIT;
Un nuevo evento aparece con "op":"c" y la fila completa en después.
Una ACTUALIZACIÓN muestra "op":"u" con ambos antes y después poblado.
Un DELETE muestra "op":"d" con antes poblado y después nulo.
Latencia sub-segundo en estado estacionario.
Paso 6: Configurar el Target de PostgreSQL
En srv2, crea el usuario de destino, la base de datos y el esquema, y permite conexiones remotas desde srvdebezium.
sudo -u postgres psql -c "CREATE USER banking WITH PASSWORD 'banking';"
sudo -u postgres psql -c "CREATE DATABASE bankingdb OWNER banking;"
sudo -u postgres psql -d bankingdb -c "CREATE SCHEMA banking AUTHORIZATION banking;"
Editar los dos archivos de configuración de PostgreSQL en srv2. listen_addresses = '*' le dice a PostgreSQL que acepte conexiones en todas las interfaces de red, no solo en localhost. El pg_hba.conf línea permite a cualquier usuario y base de datos desde el 192.168.0.0/24 subred para autenticarse con SCRAM (el protocolo seguro de contraseñas cifradas), que es cómo el conector sink JDBC de Debezium accederá a la base de datos.
# /etc/postgresql/18/main/postgresql.conf
listen_addresses = '*'
# /etc/postgresql/18/main/pg_hba.conf
host all all 192.168.0.0/24 scram-sha-256
sudo systemctl restart postgresql
En srvdebezium, registra el conector JDBC sink.
En RegexRouter SMT despoja oracle.BANCA. prefijo de cada tema antes de que se convierta en el nombre de la tabla de destino, por lo que oracle.BANCARIO.TRANSACCIONES mapas a banca.transacciones en lugar de banca.oracle_banca_transacciones.
curl -i -X POST -H "Content-Type:application/json" \
http://localhost:8083/connectors/ -d '{
"name": "jdbc-sink-connector",
"config": {
"connector.class": "io.debezium.connector.jdbc.JdbcSinkConnector",
"tasks.max": "1",
"connection.url": "jdbc:postgresql://192.168.0.181:5432/bankingdb",
"connection.username": "banking",
"connection.password": "banking",
"insert.mode": "upsert",
"delete.enabled": "true",
"primary.key.mode": "record_key",
"schema.evolution": "basic",
"topics.regex": "oracle\\.BANKING\\..+",
"table.name.format": "banking.${topic}",
"transforms": "route",
"transforms.route.type": "org.apache.kafka.connect.transforms.RegexRouter",
"transforms.route.regex": "oracle\\.BANKING\\.(.*)",
"transforms.route.replacement": "$1"
}
}'
A los pocos segundos del registro, aparecen las filas de instantánea en PostgreSQL.
Las 18 filas de BANKING se replican en menos de un minuto.
Cualquier cambio posterior en Oracle se propaga a PostgreSQL en segundos.
Paso 7: Agregar una nueva tabla en medio del flujo
Aquí es donde la canalización demuestra su valía.
Añadir un PRÉSTAMOS tabla a BANCO mientras la replicación se está ejecutando.
CREATE TABLE loans (
loan_id NUMBER(10) PRIMARY KEY,
customer_id NUMBER(8) NOT NULL,
loan_type VARCHAR2(30),
principal NUMBER(15,2) NOT NULL,
interest_rate NUMBER(5,2),
start_date DATE,
status VARCHAR2(20),
CONSTRAINT fk_loan_customer FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);
INSERT INTO loans VALUES (1, 1001, 'MORTGAGE', 250000.00, 3.25, DATE '2023-01-15', 'ACTIVE');
INSERT INTO loans VALUES (2, 1002, 'AUTO', 18000.00, 4.50, DATE '2024-06-01', 'ACTIVE');
INSERT INTO loans VALUES (3, 1003, 'PERSONAL', 5000.00, 6.75, DATE '2025-02-10', 'ACTIVE');
COMMIT;
El conector de Oracle capta la nueva tabla porque coincide BANCOS\..*.
Un tema nuevo oracle.BANKING.PRESTAMOS se aparece en Kafka.
El sink JDBC capta ese tema porque coincide oracle\.BANKING\..+.
Una mesa nueva banca.préstamos se crea en PostgreSQL con las tres filas.
Sin reconfiguración del conector.
No reiniciar.
No redesplegar.
La compensación del esquema.evolución
schema.evolution: básico es lo que hizo la autocreación de banca.préstamos trabajar sin intervención manual.
También es lo que descalifica esa configuración para la producción.
Ejecutar bancaria en PostgreSQL después de la replicación con esta configuración y la tabla se ve así:
Table "banking.accounts"
Column | Type | Nullable
--------------+--------------------------------+----------
account_id | bigint | not null
customer_id | integer | not null
branch_id | integer | not null
account_type | text |
balance | numeric(15,2) |
opened_at | timestamp(6) without time zone |
Los tipos numéricos y de fecha se replican exactamente: entero largo, entero, numeric(15,2), marca de tiempo(6). Se conservan las restricciones NOT NULL en las columnas numéricas.
Las columnas de cadena siguen aterrizando como texto independientemente de la longitud de origen. El receptor JDBC trata texto y varchar tan funcionalmente equivalente — mismo almacenamiento, mismo rendimiento — para que elija texto incondicionalmente.
DONDE customer_id = 1001 ahora funciona sin comillas. equilibrio está correctamente numeric(15,2). La réplica es, aproximadamente, del tipo 80% con fidelidad de tipo.
El espacio restante — las restricciones de longitud de VARCHAR — depende de cuál de las tres aproximaciones elijas:
| Configuración | Tipos numéricos | Tipos de cadena | Fidelidad |
|---|---|---|---|
No datatype.propagate.source.type | texto en todas partes | texto en todas partes | ~0% |
datatype.propagate.source.type establecer (este laboratorio) | exacto — bigint, entero, numérico(p,s) | texto, pérdida de longitud | ~80% |
ora2pg esquema + schema.evolution discapacitado | exacto | exacto — VARCHAR(n) conservado | 100% |
Para máxima fidelidad en producción:
- Genera el esquema de PostgreSQL de antemano utilizando ora2pg.
El esquema obtiene tipos exactos:NUMERIC(15,2)para cantidades,ENTEROpara identificaciones, apropiadoVARCHAR(n)longitudes. - Desactivar
schema.evolutionen el conector del fregadero.
Debezium transmite datos al esquema existente sin modificarlo.
La función de evolución de esquemas es para laboratorios y prototipos: útil para demostrar que el proceso funciona, pero insuficiente para producción.
El retraso en el descubrimiento de la nueva tabla
Cuando una nueva tabla aparece en Oracle mientras la replicación está en ejecución, hay un pequeño pero real retraso antes de que aparezca en PostgreSQL.
El primero SELECCIONE en la nueva tabla de PostgreSQL puede devolver la relación no existe aunque el tema de Kafka ya esté poblado.
La secuencia es:
- Oracle confirma el DDL; la nueva tabla aparece en el registro de rehacer.
- Debezium captura el DDL y crea el tema de Kafka.
En este punto el tema existe, pero el conector del sink aún no lo ha visto. - Los INSERTs se publican en el nuevo tema.
- El conector del sink eventualmente actualiza sus metadatos de tema.
El predeterminadometadata.max.age.msson 5 minutos, aunque Connect normalmente se actualiza con más frecuencia.
Cuando lo hace, el "sink" descubre el nuevo tema, lee el esquema del primer evento, ejecutaCREAR TABLAen PostgreSQL víaschema.evolution: básico, y luego se aplican los eventos. - La tabla ahora existe en PostgreSQL.
Retraso típico de descubrimiento de extremo a extremo: 5-30 segundos.
En una migración real, esto importa si se espera que una aplicación escriba en una tabla completamente nueva de Oracle y la lea inmediatamente desde PostgreSQL.
Dos maneras de manejarlo:
- Bajar
consumer.override.metadata.max.age.msen la configuración del conector de sink (por ejemplo, a 5 segundos) para un descubrimiento más rápido. - Pre-crea tablas en PostgreSQL con tipos correctos y desactívalas
schema.evolution— el patrón de producción recomendado anteriormente.
Las tablas existen antes de que fluya ningún dato.
Problemas en la producción
Algunas cosas a tener en cuenta en producción que el laboratorio no revela.
Tablas sin claves primarias.
Los eventos UPDATE y DELETE de Debezium están indexados por la clave primaria.
Las tablas sin una clave primaria (PK) pueden ser "snapshotizadas" y las inserciones (INSERTs) replicadas, pero las actualizaciones (UPDATEs) y eliminaciones (DELETEs) no pueden aplicarse a PostgreSQL.
Audita el esquema de origen para tablas sin clave primaria antes de definir el alcance de la migración.
Retención de registros de archivo de LogMiner.
LogMiner solo puede analizar registros de archivo que aún existen en el disco.
Si su política de retención elimina los registros de archivo después de 24 horas y Debezium se retrasa más que eso, la canalización no puede reanudarse desde donde se detuvo.
Tamaño del registro de archivo para la retención, para el peor escenario de inactividad de Debezium, multiplique su retención habitual por 3 para mayor seguridad.
Persistencia de contenedores.
Correr docker run -it ata el contenedor a la terminal.
Cerrar la terminal detiene el contenedor y rompe la tubería.
Utilice -d (desvinculado) para todo lo que dure más que una prueba manual.
Compensaciones del grupo de consumidores.
Eliminar un conector de Sink y recrearlo con el mismo nombre no restablece su posición en Kafka.
El nuevo conector recoge en el offset confirmado anterior, omitiendo cualquier evento en cola entre medias.
Restablecer los desplazamientos explícitamente con kafka-consumer-groups.sh --reset-offsets --to-earliest antes de volver a registrarse.
Nombre del esquema en mayúsculas.
Los nombres de esquema de Oracle son mayúsculas por defecto.
En schema.include.list el valor en la configuración del conector debe coincidir exactamente BANCA, no banca.
Los nombres de los temas del lado del fregadero siguen el caso de Oracle, razón por la cual RegexRouter elimina un prefijo en mayúsculas.
Preguntas frecuentes
¿Puede Debezium migrar el esquema de Oracle, o solo los datos?
Solo los datos.
Debezium captura eventos DML — INSERT, UPDATE, DELETE — del registro de rehacer de Oracle.
Las definiciones de esquema, los procedimientos almacenados, los desencadenadores, las vistas y las secuencias deben migrarse por separado, normalmente con ora2pg.
El `schema.evolution: basic feature` puede crear tablas de destino automáticamente, pero con tipos simplificados y sin restricciones: bueno para laboratorios, malo para producción.
¿Cuál es la latencia entre Oracle y PostgreSQL?
Unos segundos en estado estable en una configuración saludable de LogMiner.
La latencia aumenta bajo una carga intensa de escritura o si la generación de registros de archivo supera la tasa de lectura de LogMiner.
Planifique un desfase inferior a un minuto y monitoreelo explícitamente con kafka-consumer-groups.sh –describe.
¿Está LogMiner obsoleto en Oracle 19c o 21c?
LogMiner es el mecanismo CDC admitido en Oracle 19c.
En Oracle 21c y posteriores, Oracle introdujo XStream como una alternativa de pago.
Debezium sigue admitiendo ambos: el adaptador LogMiner es el predeterminado y funciona sin una licencia adicional de Oracle.
¿Esto puede ejecutarse contra Oracle Standard Edition?
Sí, con advertencias.
LogMiner está disponible en Standard Edition 2, pero se requiere el registro suplementario y el modo archivelog, y algunas optimizaciones disponibles en Enterprise Edition no lo están.
Prueba contra la edición exacta que tengas.
¿Puedo usar Debezium para migración de un solo disparo sin mantenerlo en ejecución?
Sí.
Puedes ejecutar la fase de instantánea, esperar a que se complete y luego detener el conector.
Pero rara vez es la decisión correcta; si vas a configurar Debezium, puedes dejar que transmita hasta el cambio para tener un pipeline probado y sin latencia listo cuando la aplicación se reoriente.
En resumen
Debezium convierte una migración de Oracle a PostgreSQL de una simple operación de volcar y restaurar en un canal controlable y observable que puedes ejecutar durante semanas antes del cambio.
LogMiner lee los registros de rehacer de Oracle, Kafka mantiene el flujo de eventos y el sink JDBC aplica los cambios a PostgreSQL con una latencia inferior al minuto.
El resultado es un canal de replicación en tiempo real que puede validar, reproducir y cancelar limpiamente — la base de cualquier migración con tiempo de inactividad cero o casi cero.
Si está planeando una migración de Oracle a PostgreSQL y desea ayuda para diseñar la fase de corte o revisar su arquitectura CDC, ponerse en contacto
