# Migración de Oracle a PostgreSQL sin tiempo de inactividad: Un desglose técnico
Migrar de Oracle a PostgreSQL sin detener el servicio es una tarea desafiante pero factible. En este artículo, desglosamos una estrategia de migración paso a paso basada en un proyecto real con microservicios de Spring Boot, donde el impacto cero en los usuarios fue un requisito clave. Usar CDC mediante Debezium permitió la sincronización de datos en tiempo real, evitando el tiempo de inactividad y minimizando riesgos.
Preparación: Análisis de la estructura y los datos
La primera etapa implica una auditoría profunda de la base de datos actual. Necesitas entender el volumen de datos, la distribución de tipos de campos, la presencia de registros obsoletos y construcciones específicas de Oracle sin equivalentes directos en PostgreSQL. Limpiar datos irrelevantes reduce el volumen de migración y acelera el proceso.
Un aspecto clave es el mapeo de tipos de datos. Por ejemplo:
NUMBER(1,0)→BOOLEANVARCHAR2→TEXToVARCHARDATE→TIMESTAMP WITHOUT TIME ZONECLOB→TEXT
Para el análisis, usamos esta consulta SQL:
select distinct DATA_TYPE
from ALL_TAB_COLUMNS
where owner = 'schemat'
order by DATA_TYPE
Basados en los resultados, creamos una tabla de mapeo de tipos de datos que sirvió de base para todas las transformaciones posteriores. También es crucial tener en cuenta las diferencias en el manejo de NULL y cadenas vacías: en Oracle, una cadena vacía se trata como NULL, pero no en PostgreSQL. Esto requiere ajustes en la lógica de negocio y las consultas.
Adaptación del esquema y Liquibase
Simplemente cambiar el driver de la base de datos causará errores. Los scripts de migración deben adaptarse para PostgreSQL. Para ello:
- Las operaciones DDL y DML se separan mediante contextos de Liquibase — la DML se deshabilita temporalmente.
- Los scripts se prueban de forma iterativa: después de cada cambio, se ejecuta el changelog, seguido de una limpieza y pruebas de humo.
- Se verifican las precondiciones para su corrección y se asegura la consistencia del esquema con Oracle.
Una atención especial se presta a las secuencias. Si no están sincronizadas, los nuevos ID podrían entrar en conflicto con los datos históricos. La solución:
- Al iniciar la aplicación, verifica el valor actual de la secuencia en PostgreSQL.
- Si es menor que en Oracle, adelántalo con un margen de seguridad.
- La lógica es idempotente: ejecuciones repetidas no causan fallos.
Como resultado, el esquema objetivo de PostgreSQL se ensambló en una única solicitud de extracción, listo para la carga de datos.
Ajustes en el código de la aplicación
Después de lanzar exitosamente la aplicación contra un PostgreSQL vacío, emergen errores a nivel de Java. Principales cambios:
- Reemplaza la anotación
@Lobcon@Column(columnDefinition = "text"). - Maneja NULL en consultas SQL nativas, especialmente en construcciones
IN (...). - Cambia de banderas numéricas (0/1) a
boolean. - Ajusta la lógica de comparación de cadenas considerando las diferencias entre Oracle/PostgreSQL.
- Reescribe consultas nativas para el dialecto de PostgreSQL.
Las pruebas se realizaron a nivel de pruebas unitarias e integradas. Enfoque especial en casos límite: cadenas vacías, valores NULL, campos de texto grandes.
Implementación de CDC mediante Debezium y Kafka Connect
Elegimos la pila clásica: Debezium + Kafka Connect. Arquitectura:
- El conector de origen (Debezium Oracle) lee el registro de redo y genera eventos CDC.
- Los eventos se envían a Kafka (un tema por tabla).
- El conector de destino (JDBC Sink) aplica los cambios a PostgreSQL en el mismo orden.
Etapas de configuración:
- Instantánea inicial — copia completa de datos en el momento de inicio.
- Cambios en streaming — replicación continua de INSERT/UPDATE/DELETE desde el registro de redo.
- Preservación del orden — garantía de secuencia de cambios mediante LogMiner.
Imágenes utilizadas:
quay.io/debezium/kafka:3.0quay.io/debezium/zookeeper:3.0quay.io/debezium/connect:3.0provectuslabs/kafka-ui:0.7.2(para monitoreo)
La configuración se realiza mediante REST API usando curl. La interfaz de usuario de Debezium fue inestable durante la migración, por lo que las configuraciones se pasaron manualmente en formato JSON.
Ejemplo de configuración del conector de origen:
{
"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"
}
}
Ejemplo de configuración del conector de destino:
{
"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"
}
}
Algunas tablas (p. ej., las con claves compuestas) requieren configuraciones separadas. Cada conector se prueba de forma aislada.
Cambio final y control de calidad
Después de completar la instantánea inicial y estabilizar el streaming:
- Se lanzan instancias de prueba de los servicios conectados a PostgreSQL.
- Se realizan pruebas de extremo a extremo: API, UI, procesos en segundo plano.
- Se lleva a cabo pruebas de carga con datos similares a producción.
- En el momento de carga mínima, se cambia el DNS o las rutas de ingress a las nuevas instancias.
- Se monitorean logs, métricas y alertas durante 24–48 horas.
El rollback solo es posible hasta el punto de cambio. Después de eso, el sistema funciona exclusivamente en PostgreSQL. Se retienen copias de seguridad de Oracle para recuperación de datos de emergencia.
Lecciones clave
- No hay una solución universal — cada proyecto necesita adaptación personalizada.
- CDC sin escrituras dobles — un compromiso aceptable con unos segundos de retraso.
- Sincronización de secuencias — esencial para evitar conflictos de ID.
- Pruebas en cada etapa — la clave para una migración estable.
- Debezium + Kafka Connect — una pila flexible y confiable para migraciones en línea.
La migración tomó 18 horas incluyendo la preparación, pero el tiempo de inactividad real para los usuarios fue de 0 segundos. El proyecto ha estado funcionando exitosamente en PostgreSQL durante más de un año sin regresiones.
— Editorial Team
Aún no hay comentarios.