Migrar una base de datos de un motor a otro, por ejemplo de Oracle o Informix a PostgreSQL, parece a primera vista un problema simple: convertir el esquema, traducir el código SQL y trasladar los datos. Si fuera solo eso, las migraciones serían sencillas. Pero en un sistema real alrededor de la base de datos hay todo un ecosistema de aplicaciones, procesos batch, ETL, data warehouses y otros sistemas que dependen de ella, directa o indirectamente.
Por eso conviene plantear la migración como un proceso de ingeniería basado en pruebas, mediciones e iteraciones sucesivas. En este artículo veremos cinco aspectos: disponer de una referencia objetiva del sistema actual, migrar y automatizar la conversión del esquema y los datos, probar todas las aplicaciones dependientes, preparar el switchover y un backup plan, y monitorizar y operar el nuevo sistema.
1. Disponer de tests: medir antes de actuar
Antes de empezar necesitamos un conjunto representativo de pruebas funcionales y de rendimiento del sistema actual, incluidas pruebas de carga que reproduzcan en lo posible las condiciones reales. Que una aplicación funcione con uno o dos usuarios no dice nada de cómo se comportará con cientos de operaciones concurrentes.
Ejecutamos esas pruebas sobre el sistema original para obtener una referencia y las repetimos sobre el nuevo tras la migración. Las diferencias nos dicen dónde hay un problema real. Si una consulta que tardaba 200 ms sigue tardando lo mismo, no hay nada que resolver. Si pasa a tardar cinco segundos, tenemos un problema concreto, medible y reproducible.
medir → migrar → probar → detectar diferencias → corregir → volver a medir
Así evitamos uno de los errores más habituales: dedicar semanas a problemas hipotéticos, como optimizar consultas que sospechamos que irán peor o modificar aplicaciones anticipándonos a fallos que quizá nunca lleguen, mientras los problemas reales siguen ocultos.
2. Migrar el esquema y los datos
Con la referencia inicial ya podemos migrar. Migrar el esquema es más que crear tablas: hay que identificar todos los objetos del sistema original que tengan correspondencia en PostgreSQL, directa o mediante alguna transformación. Eso incluye tipos de datos, tablas, restricciones, índices, secuencias y otros mecanismos de generación de identificadores, vistas, triggers, funciones, procedimientos almacenados y, por supuesto, los datos.
Los objetos no presentan la misma dificultad. Las tablas y los datos suelen ser relativamente directos, y según el volumen podemos usar scripts propios, herramientas ETL o conversores. Las vistas y, sobre todo, las funciones, procedimientos y triggers son otra cosa. El lenguaje procedural de Oracle o Informix difiere del de PostgreSQL en sintaxis, tipos, funciones disponibles, cursores, tratamiento de excepciones y algunos comportamientos propios de cada motor. Aquí estamos traduciendo código de un lenguaje a otro.
La traducción puede hacerse a mano, con ayuda de un LLM, con un producto basado en reglas y heurísticas o con un transpiler. Un transpiler es un traductor entre ambos lenguajes: si conoce formalmente origen y destino, aplica una regla conocida para generar el equivalente, y la transformación es determinista, a diferencia del carácter probabilístico de un LLM. No hay que elegir una sola opción. Podemos automatizar la mayoría de los casos, apoyarnos en una IA para otros y reservar la intervención manual para los que realmente la necesiten.
Una migración que vamos a repetir muchas veces
Esta migración no se hará una sola vez. La repetiremos muchas veces, y cada ejecución incorporará las correcciones de la anterior, nuevas reglas de traducción y mejoras en la transferencia de datos. Por eso conviene automatizar todo lo posible desde el principio. Si cada iteración nos obligara a traducir a mano cientos de objetos y a recordar una secuencia de operaciones, el procedimiento sería lento, difícil de reproducir y propenso a errores.
Cuando aparezca un error de traducción, es preferible corregir el mecanismo que lo generó y no solo el resultado. Si veinte funciones usan una misma construcción mal traducida, podríamos corregir las veinte a mano, pero es mejor modificar el traductor para que la siguiente iteración las genere bien. Cada problema resuelto mejora el proceso completo, y el día de la migración definitiva no haremos nada nuevo: ejecutaremos una vez más un procedimiento que ya hemos realizado y corregido muchas veces.
3. Probar y adaptar todas las aplicaciones dependientes
Con el esquema y los datos migrados llega probablemente la fase más laboriosa: comprobar que siguen funcionando todos los sistemas que dependen de esa base de datos. Que PostgreSQL tenga las tablas, que los datos estén presentes y que las funciones compilen no es suficiente. Tiene que funcionar el sistema completo.
Hay que probar las aplicaciones de usuario, los servicios backend, los procesos batch, las tareas de cron u otros planificadores, los ETL, los sistemas de reporting, los data warehouses y cualquier otro sistema que lea o modifique datos de esa base. Estas pruebas nos dirán qué aplicaciones necesitan adaptación. Si una aplicación funciona contra PostgreSQL y supera las pruebas funcionales y de rendimiento, no hay motivo para tocarla.
El SQL puede estar en cualquier parte
Cuando aparezcan incompatibilidades, las modificaciones pueden hacerse a mano, con ayuda de una IA o con herramientas que detecten SQL y traduzcan ciertas construcciones. Esta parte es más complicada de lo que parece. El SQL de una aplicación no siempre es una sentencia identificable en el código: puede estar repartido entre cadenas, oculto tras un ORM, definido en ficheros de configuración o construido dinámicamente a partir de parámetros. Incluso puede haber consultas complejas generadas al vuelo que dependan de los datos de entrada, de modo que la sentencia completa solo existe durante la ejecución.
Por eso, aunque dispongamos de análisis estático del código fuente, seguiremos necesitando las pruebas, que revelarán los casos que el análisis no localizó.
Conservar todo lo que vayamos corrigiendo
Cada modificación de esta fase debe quedar registrada. Lo lógico es usar un sistema de control de versiones como Git y, cuando convenga, mantener ramas específicas de la migración. Así cada iteración parte de la anterior en lugar de reconstruir los cambios, sabemos exactamente qué se ha modificado y distintos equipos pueden revisarlo, probarlo y revertirlo si hace falta. En proyectos con decenas de aplicaciones implicadas, esta disciplina es especialmente importante.
4. Preparar el switchover y el backup plan
Cuando hayamos migrado las bases de datos, adaptado las aplicaciones y superado las pruebas funcionales, de rendimiento y de carga, podremos plantear el paso a producción. A estas alturas ya conocemos la ventana de tiempo disponible para el cambio, y tras varias iteraciones sabemos cuánto tarda realmente la migración de los datos. Podemos diseñar el switchover con medidas obtenidas en las pruebas y no con estimaciones.
La migración final de los datos
Según el volumen de datos y la ventana disponible, podemos hacer una migración completa durante el switchover o dejar migrada de antemano una parte y transferir solo lo pendiente. La migración completa simplifica el procedimiento, pero puede exigir una ventana demasiado grande. La parcial o incremental la reduce, a cambio de más complejidad. También podemos reducir tiempos con más recursos o paralelizando operaciones. Hay un compromiso entre tiempo, recursos y complejidad: cuanto menor sea la ventana, más complejidad habrá que asumir.
La carga masiva es más compleja de lo que parece
Mover cientos de millones de registros entre dos motores parece cuestión de copiar tablas, pero con una ventana limitada se convierte en un problema de rendimiento. Las pruebas anteriores ya nos habrán mostrado la forma más rápida y fiable de hacerlo.
Durante la carga puede convenir eliminar o desactivar temporalmente lo que ralentice las inserciones: índices, ciertos constraints, checks o triggers. También hay que usar los mecanismos de transferencia más rápidos, como COPY en PostgreSQL. Y hay que mirar la salida: si la extracción desde Oracle o Informix es lenta, ella limitará todo el proceso.
Una vez transferidos los datos hay que reconstruir los índices, restaurar las restricciones eliminadas y comprobar que todo ha quedado bien configurado. Hay dos detalles fáciles de olvidar. Si hemos cargado explícitamente claves primarias generadas por secuencias o campos identity, hay que ajustar esos mecanismos para que las siguientes inserciones continúen desde el valor correcto. Y hay que ejecutar ANALYZE sobre las tablas cargadas, porque sin estadísticas actualizadas el optimizador puede elegir planes malos justo en las primeras horas en producción.
detener cambios → transferir datos → reconstruir, ajustar y analizar → validar → cambiar las aplicaciones
Lo importante es que, llegado ese momento, ya hayamos ensayado todo el procedimiento: cuánto tarda la transferencia, cuánto la reconstrucción de índices, cuánto duran las comprobaciones y cuánto hace falta para volver a poner en marcha las aplicaciones.
Preparar un backup plan
Debemos asumir que el switchover puede fallar. Por eso necesitamos un backup plan, el plan de contingencia que ejecutaremos si todo falla. Aquí no hablamos de copias de seguridad de la base de datos.
La decisión clave es qué hacer con las transacciones realizadas en el nuevo sistema si luego hay que volver al antiguo. Mientras PostgreSQL no acepte escrituras, ambos mundos se mantienen separados con facilidad. El problema aparece cuando empiezan a hacerse transacciones nuevas. Entonces hay que responder a una pregunta técnica y de negocio:
¿Podemos permitirnos perder esas transacciones si tenemos que volver al sistema anterior?
En algunos sistemas puede ser aceptable, porque las operaciones podrían repetirse o reconstruirse, o su volumen sería tan pequeño que se recuperarían de otra forma. En otros, perder una sola transacción es inadmisible, y el backup plan tendrá que incluir un mecanismo para conservarlas o trasladarlas de vuelta al sistema anterior.
Una posible cuarentena
También podemos prever un periodo intermedio tras el switchover. Si el negocio lo permite, mantenemos el nuevo sistema en solo lectura, o con determinadas escrituras, mientras comprobamos que las aplicaciones funcionan y que el comportamiento es el esperado. Sería una cuarentena. Mientras no se hayan generado transacciones nuevas, volver al sistema anterior sigue siendo relativamente sencillo. Muchos sistemas no podrán permitirse una ventana prolongada en solo lectura, pero cuando sea posible da un margen adicional antes de cruzar el punto más delicado: permitir escrituras reales en producción.
El switchover y el backup plan tienen que diseñarse conjuntamente.
5. Monitorizar y saber operar el nuevo sistema
Este punto tiene que empezar antes de que termine el anterior. Cuando iniciemos el switchover, la monitorización de PostgreSQL debe estar instalada, configurada y probada. Tenemos que poder observar el rendimiento general, las consultas lentas, los errores, las sesiones, las conexiones, las transacciones, los bloqueos, las esperas, la CPU y la memoria, el I/O, el almacenamiento y, cuando existan, la replicación y la alta disponibilidad.
Esa información será especialmente valiosa en las primeras horas y días. Si aparece un problema, necesitaremos saber qué ocurre para decidir si podemos resolverlo o si es el momento de activar el backup plan. Volvemos al principio: medir antes de actuar. Decir que PostgreSQL «parece ir lento» sirve de poco. Necesitamos saber qué consulta se ha ralentizado, qué sesiones esperan, qué bloqueos hay, qué pasa con el I/O o qué errores reciben las aplicaciones.
Saber operar el sistema
Detectar un problema de poco sirve si no sabemos resolverlo. Antes de llegar a producción tenemos que dominar la operativa habitual y de emergencia de PostgreSQL: backups, restores, recuperación, alta disponibilidad, replicación, arranque y parada de servidores, gestión de usuarios y conexiones, bloqueo temporal de accesos, terminación de sesiones, diagnóstico de bloqueos y análisis de consultas problemáticas. Al llegar al switchover tenemos que ser DBA competentes en PostgreSQL.
Idealmente conoceremos el nuevo sistema al menos tan bien como el antiguo, y durante los primeros días mejor preparados de lo habitual, porque entonces surgirán situaciones que no vimos en las pruebas. Si hay un problema crítico en producción, ese no es el momento de estudiar cómo se diagnostica un bloqueo, cómo se recupera un servidor o qué pasa si se reinicia un servicio.
Dejarse acompañar por especialistas
Por eso, durante el switchover y los primeros días puede ser muy recomendable contar con especialistas con experiencia real administrando PostgreSQL en producción. Lo valioso es que, además de conocer el producto, estén acostumbrados a diagnosticar problemas de rendimiento, concurrencia, recuperación y alta disponibilidad en sistemas reales. Con el tiempo, el equipo interno ganará esa experiencia, pero los primeros días son aquellos en los que una decisión equivocada cuesta más.
La migración termina cuando podemos observar el sistema, entender lo que ocurre y reaccionar correctamente cuando algo no funciona como esperábamos. Que PostgreSQL empiece a recibir conexiones es solo un paso intermedio.
Migrar bases de datos con garantías: un proceso de ingeniería
Migrar de un motor de base de datos a otro no es trivial. Estamos sustituyendo una de las piezas centrales de un sistema informático, y por eso el proceso debe ser controlado, medible y repetible. Quienes hemos hecho este tipo de proyectos sabemos que se puede hacer bien, y también que es muy fácil infravalorarlo si se ve solo como un problema de conversión de bases de datos.
medir → migrar → probar → detectar → corregir → repetir
Con buenas pruebas sabremos qué funciona y qué no. Con la migración automatizada podremos repetirla las veces necesarias. Probando todas las aplicaciones sabremos cuáles necesitan cambios. Y con un switchover ensayado, un backup plan y un equipo que sabe operar el nuevo motor, el paso a producción deja de ser una apuesta y pasa a ser un procedimiento conocido.
Entonces, ¿merece la pena?
En el caso de PostgreSQL creemos que sí. Es un sistema gestor maduro, muy fiable y con excelente rendimiento, especialmente en cargas transaccionales. Según el sistema de partida, el ahorro puede ser considerable: en instalaciones grandes las licencias, el mantenimiento y el soporte de ciertos proveedores suman cifras muy importantes, y una migración bien planteada puede amortizarse eliminando buena parte de esos costes.
Otra ventaja es que PostgreSQL es software libre y de código abierto. Podemos estudiar su código, entender el optimizador, analizar cómo implementa la concurrencia o investigar por qué toma una decisión. No hay que tratar el SGBD como una caja negra. Además, a su alrededor hay un gran ecosistema de empresas, desarrolladores, DBA, consultores y proveedores, y se usa en sistemas de todo tipo, incluidos los críticos y de gran tamaño.
Con todo, esas ventajas no deben llevarnos a minimizar el trabajo necesario. No queremos desanimar a nadie, al contrario: hay razones técnicas y económicas muy poderosas para migrar. Pero conviene conocer la dificultad de antemano y tratar la migración como lo que es, un proyecto de ingeniería.
Los problemas aparecerán. Lo importante es haber construido un procedimiento que nos permita encontrarlos antes de llegar a producción, medirlos, corregirlos y volver a probar. Con cada iteración reducimos la incertidumbre, hasta que la migración se convierte en un proceso que ya hemos ejecutado, medido y corregido muchas veces.
Se puede hacer y merece la pena, pero hay que hacerlo bien. Necesitamos haber hecho las pruebas suficientes para saber que funciona.
Una migración de bases de datos no es un acto de fe. Es un proceso de ingeniería.
Preguntas frecuentes sobre la migración de bases de datos
Es necesario disponer de pruebas funcionales, de rendimiento y de carga del sistema original. Sus resultados servirán como referencia para detectar diferencias tras la migración.
Porque el procedimiento se repetirá varias veces. La automatización permite incorporar correcciones, mejorar la traducción de objetos y reducir errores entre iteraciones.
Deben probarse las aplicaciones de usuario, los servicios backend, los procesos batch, las tareas programadas, los ETL, los sistemas de reporting y los data warehouses que dependen de ella.
Debe definir cómo regresar al sistema anterior si el cambio falla y qué hacer con las transacciones registradas en PostgreSQL después de comenzar a aceptar escrituras.
Se deben reconstruir los índices, restaurar las restricciones eliminadas, ajustar las secuencias o campos identity cuando proceda y actualizar las estadísticas mediante ANALYZE.
Porque permite identificar consultas lentas, bloqueos, esperas, errores y problemas de recursos, y decidir con información si corregir una incidencia o activar el plan de contingencia.
Planifique su migración a PostgreSQL con Hopla!
Prepare la migración de bases de datos a PostgreSQL para su empresa.
Contacte con el equipo de Hopla! para analizar los requisitos de su proyecto y definir los siguientes pasos.