{"id":6655,"date":"2026-04-02T14:25:10","date_gmt":"2026-04-02T12:25:10","guid":{"rendered":"https:\/\/rootfan.com\/?p=6655"},"modified":"2026-04-20T22:49:52","modified_gmt":"2026-04-20T20:49:52","slug":"buenas-practicas-de-migracion-de-oracle-a-postgresql","status":"publish","type":"post","link":"https:\/\/rootfan.com\/es\/oracle-to-postgresql-migration-best-practices\/","title":{"rendered":"Pr\u00e1cticas recomendadas para la migraci\u00f3n de Oracle a PostgreSQL: una lista de verificaci\u00f3n para administradores y arquitectos de bases de datos"},"content":{"rendered":"<p><strong>En resumen<\/strong> La mayor\u00eda de las migraciones de Oracle a PostgreSQL no fallan por las herramientas, sino por los pasos omitidos.<br>Esta lista de verificaci\u00f3n cubre todas las fases, desde la evaluaci\u00f3n previa a la migraci\u00f3n hasta el corte: las trampas de tipos de datos que causan p\u00e9rdida silenciosa de datos, las diferencias de secuencia y NULL que rompen las aplicaciones despu\u00e9s de la puesta en marcha, los pasos de prueba que se eliminan cuando los plazos se acortan, y las decisiones de corte que determinan si se puede revertir si algo sale mal.<\/p>\n\n\n\n<!--more-->\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<p>La migraci\u00f3n de Oracle a PostgreSQL parec\u00eda sencilla sobre el papel.<\/p>\n\n\n\n<p>El esquema era sencillo: cincuenta tablas, sin particiones, PL\/SQL ligero.<\/p>\n\n\n\n<p>El equipo ejecut\u00f3 ora2pg, los datos se cargaron limpiamente, los recuentos de filas coincid\u00edan.<\/p>\n\n\n\n<p>Salieron en vivo un s\u00e1bado por la ma\u00f1ana.<\/p>\n\n\n\n<p>El lunes, la cola de asistencia estaba llena.<\/p>\n\n\n\n<p>Todas las marcas de tiempo del sistema indicaban medianoche.<\/p>\n\n\n\n<p>Las columnas DATE de Oracle hab\u00edan sido mapeadas a DATE de PostgreSQL - que almacena s\u00f3lo la fecha.<\/p>\n\n\n\n<p>Dos a\u00f1os de datos temporales, descartados silenciosamente.<\/p>\n\n\n\n<p>Sin error.<\/p>\n\n\n\n<p>No hay advertencia.<\/p>\n\n\n\n<p>Ese \u00fanico error -un valor por defecto err\u00f3neo en la configuraci\u00f3n de la migraci\u00f3n- se puede evitar.<\/p>\n\n\n\n<p>Entonces, cada modo de falla en esta lista tambi\u00e9n.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<div class=\"wp-block-rank-math-toc-block\" id=\"rank-math-toc\"><h2>\u00cdndice<\/h2><nav><ul><li><a href=\"#what-is-the-most-common-cause-of-oracle-to-postgre-sql-migration-failures\">\u00bfCu\u00e1l es la causa m\u00e1s com\u00fan de los fallos de migraci\u00f3n de Oracle a PostgreSQL?<\/a><\/li><li><a href=\"#phase-1-pre-migration-assessment\">Fase 1: Evaluaci\u00f3n previa a la migraci\u00f3n<\/a><\/li><li><a href=\"#phase-2-schema-conversion\">Fase 2: Conversi\u00f3n de esquemas<\/a><\/li><li><a href=\"#phase-3-data-migration\">Fase 3: Migraci\u00f3n de datos<\/a><\/li><li><a href=\"#phase-4-application-changes\">Fase 4: Cambios en la aplicaci\u00f3n<\/a><\/li><li><a href=\"#phase-5-testing\">Fase 5: Pruebas<\/a><\/li><li><a href=\"#phase-6-cutover\">Fase 6: Transici\u00f3n<\/a><\/li><li><a href=\"#frequently-asked-questions\">Preguntas frecuentes<\/a><ul><li><a href=\"#faq-question-1775135092634\">\u00bfCu\u00e1l es el error m\u00e1s com\u00fan en una migraci\u00f3n de Oracle a PostgreSQL?<\/a><\/li><li><a href=\"#faq-question-1775135093634\">\u00bfNecesito realizar pruebas de rendimiento antes de la migraci\u00f3n?<\/a><\/li><li><a href=\"#faq-question-1775135094634\">\u00bfCu\u00e1l es el m\u00e9todo de transici\u00f3n m\u00e1s seguro para una base de datos Oracle de producci\u00f3n?<\/a><\/li><li><a href=\"#faq-question-1775135095634\">\u00bfPuedo revertir despu\u00e9s del corte si algo sale mal?<\/a><\/li><li><a href=\"#faq-question-1775135096634\">\u00bfPostgreSQL maneja NULL de la misma manera que Oracle?<\/a><\/li><\/ul><\/li><li><a href=\"#in-summary\">En resumen<\/a><\/li><\/ul><\/nav><\/div>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"what-is-the-most-common-cause-of-oracle-to-postgre-sql-migration-failures\">\u00bfCu\u00e1l es la causa m\u00e1s com\u00fan de los fallos de migraci\u00f3n de Oracle a PostgreSQL?<\/h2>\n\n\n\n<p>La causa m\u00e1s com\u00fan no es la complejidad t\u00e9cnica, sino las suposiciones incontroladas.<\/p>\n\n\n\n<p>Los equipos asumen que PostgreSQL maneja los tipos de datos, la sem\u00e1ntica de NULL y la sintaxis SQL de la misma manera que Oracle.<\/p>\n\n\n\n<p>No es as\u00ed.<\/p>\n\n\n\n<p>Las diferencias son lo bastante peque\u00f1as como para pasarlas por alto durante el desarrollo y lo bastante grandes como para interrumpir la producci\u00f3n.<\/p>\n\n\n\n<p>La lista de comprobaci\u00f3n que figura a continuaci\u00f3n se ha elaborado a partir de estos patrones de fracaso.<\/p>\n\n\n\n<p>Cada art\u00edculo existe porque alguien se lo salt\u00f3 y lo pag\u00f3 despu\u00e9s.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"phase-1-pre-migration-assessment\">Fase 1: Evaluaci\u00f3n previa a la migraci\u00f3n<\/h2>\n\n\n\n<p>La evaluaci\u00f3n debe cubrir cinco \u00e1reas: funciones espec\u00edficas de Oracle en uso, cada columna DATE que debe mapearse a TIMESTAMP, uso de cadenas vac\u00edas frente a NULL en la aplicaci\u00f3n, un recuento completo de objetos PL\/SQL y una b\u00fasqueda de SQL de dialecto Oracle en la base de c\u00f3digo.<br>Si omites alguno de estos, encontrar\u00e1s la brecha a mitad del proyecto, cuando sea costoso de arreglar.<\/p>\n\n\n\n<p>La fase de evaluaci\u00f3n determina el alcance y el coste de todo lo que viene despu\u00e9s.<br>Salt\u00e1rsela es la forma m\u00e1s r\u00e1pida de superar el presupuesto y perder la fecha de entrada en funcionamiento.<\/p>\n\n\n\n<p><strong>Auditor\u00eda de las funciones espec\u00edficas de Oracle en uso<\/strong><br>Verificar particionamiento, colas avanzadas, actualizaci\u00f3n r\u00e1pida de vistas materializadas, Oracle Text y Workspace Manager.<br>Cada una de ellas requiere una decisi\u00f3n arquitect\u00f3nica, no s\u00f3lo un cambio de sintaxis.<br>Algunos tienen equivalentes PostgreSQL.<br>Algunos requieren redise\u00f1o.<br>Identif\u00edquelos antes de que comience el proyecto, no una vez finalizada la conversi\u00f3n del esquema 80%.<\/p>\n\n\n\n<p><strong>Mapear cada columna Oracle DATE a TIMESTAMP siempre<\/strong><br>Oracle DATE almacena tanto la fecha como la hora.<br>PostgreSQL DATE almacena solo la fecha.<br>El mapeo de Oracle DATE a PostgreSQL DATE descarta silenciosamente el componente de tiempo de cada valor en esa columna.<br>No hay ning\u00fan error ni advertencia: los datos se cargan limpiamente y el tiempo desaparece.<br>Todas las columnas Oracle DATE deben mapearse a PostgreSQL TIMESTAMP en la configuraci\u00f3n de ora2pg, sin excepci\u00f3n.<\/p>\n\n\n\n<p><strong>Auditor\u00eda de cadena vac\u00eda frente al uso de NULL<\/strong><br>Oracle trata una cadena vac\u00eda (<code>''<\/code>) como NULL.<br>PostgreSQL las trata como valores distintos.<br>Una aplicaci\u00f3n que inserta <code>''<\/code> se espera que un NULL se comporte de manera diferente despu\u00e9s de la migraci\u00f3n.<br>Consultar el esquema de origen en busca de columnas con restricciones NOT NULL y comprobar el c\u00f3digo de la aplicaci\u00f3n en busca de inserciones de cadenas vac\u00edas antes de que comience la migraci\u00f3n.<\/p>\n\n\n\n<p><strong>Contar y clasificar todos los objetos PL\/SQL<\/strong><br>Ejecute el informe de evaluaci\u00f3n ora2pg (<code>ora2pg -t SHOW_REPORT<\/code>) para obtener un recuento de objetos y una estimaci\u00f3n del coste de migraci\u00f3n.<br>Registre el n\u00famero de procedimientos almacenados, funciones, paquetes, disparadores y cuerpos de paquetes.<br>Este es el principal motor del esfuerzo y el costo de migraci\u00f3n.<br>Un esquema sin PL\/SQL ni funciones espec\u00edficas de Oracle puede migrar en d\u00edas.<br>Un esquema con cincuenta procedimientos almacenados y diez paquetes lleva semanas.<\/p>\n\n\n\n<p><strong>Identificaci\u00f3n de SQL espec\u00edfico de Oracle en el c\u00f3digo de la aplicaci\u00f3n<\/strong><br>Buscar en la base de c\u00f3digo de la aplicaci\u00f3n: <code>ROWNUM<\/code>, <code>DE DUAL<\/code>, <code>NVL(<\/code>, <code>DECODE(<\/code>, <code>(+)<\/code>, <code>CONECTAR POR<\/code>, <code>FECHA_SISTEMA<\/code>, <code>ADD_MONTHS<\/code>, <code>TRUNC(<\/code>, <code>TO_DATE(<\/code>.<br>Cada incidencia es un cambio de aplicaci\u00f3n necesario tras la migraci\u00f3n de la base de datos.<br>Conocer el volumen antes de que comience el proyecto evita sorpresas en el alcance a mitad de camino.<\/p>\n\n\n\n<p><strong>Secuencia de inventario Valores CACHE y uso de CURRVAL<\/strong><br>Las secuencias de Oracle tienen un valor predeterminado de CACHE 20.<br>Las secuencias de PostgreSQL tienen como valor predeterminado CACHE 1.<br>Las inserciones de alto rendimiento se comportar\u00e1n de manera diferente.<br>Identifique tambi\u00e9n cada lugar del c\u00f3digo de la aplicaci\u00f3n que llame a <code>VALOR ACTUAL<\/code> - PostgreSQL maneja el estado de secuencia local de sesi\u00f3n de forma diferente, y la soluci\u00f3n requiere el uso de <code>REGRESANDO<\/code> o <code>lastval()<\/code>.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"phase-2-schema-conversion\">Fase 2: Conversi\u00f3n de esquemas<\/h2>\n\n\n\n<p><strong>ENCAUSAR<\/strong><br>Establece un valor de CACHE realista en la secuencia DDL generada.<br>Para la mayor\u00eda de las cargas de trabajo OLTP, CACHE 20 o superior es apropiado.<br>PostgreSQL CACHE 1 significa una escritura en disco en cada llamada de secuencia - esto es seguro pero lento a escala.<\/p>\n\n\n\n<p><strong>Columnas booleanas<\/strong><br>Oracle no tiene un tipo de datos BOOLEAN nativo.<br>Las aplicaciones normalmente almacenan valores booleanos como <code>CHAR(1)<\/code> (<code>'Y'<\/code>\/<code>'N'<\/code>) o <code>N\u00daMERO(1)<\/code> (<code>1<\/code>\/<code>0<\/code>).<br>PostgreSQL tiene un tipo BOOLEAN nativo.<br>usa ora2pg <code>MODIFICAR_TIPO<\/code> para convertir estas columnas en <code>BOLEANO<\/code> en lugar de arrastrar la soluci\u00f3n provisional de Oracle a la nueva base de datos.<br>Actualizar el c\u00f3digo de la aplicaci\u00f3n para usar <code>verdadero<\/code>\/<code>falso<\/code> en lugar de <code>'Y'<\/code>\/<code>'N'<\/code> o <code>1<\/code>\/<code>0<\/code>.<\/p>\n\n\n\n<p><strong>Caso identificador<\/strong><br>Oracle almacena los identificadores no entrecomillados en may\u00fasculas.<br>PostgreSQL almacena los identificadores no entrecomillados en min\u00fasculas.<br>Nunca entrecomille identificadores en PostgreSQL a menos que el nombre contenga caracteres especiales o may\u00fasculas y min\u00fasculas que deban ser preservados.<br>Los identificadores entre comillas en PostgreSQL distinguen entre may\u00fasculas y min\u00fasculas \u2014 <code>\"Empleado\"<\/code> y <code>empleado<\/code> son objetos diferentes.<br>El enfoque m\u00e1s seguro es dejar que ora2pg convierta todo a identificadores sin comillas en min\u00fasculas y actualizar el c\u00f3digo de la aplicaci\u00f3n para que coincida.<\/p>\n\n\n\n<p><strong>Particionamiento<\/strong><br>El particionamiento de listas, rangos y hash de Oracle se asigna directamente al particionamiento declarativo de PostgreSQL.<br>El particionamiento por intervalos de Oracle (creaci\u00f3n autom\u00e1tica de particiones de rango) no tiene un equivalente directo - implem\u00e9ntelo con una partici\u00f3n de rango y un trabajo programado para a\u00f1adir futuras particiones.<br>El particionamiento compuesto de Oracle (por ejemplo, range-hash) requiere un dise\u00f1o manual en PostgreSQL.<br>Identifique la estrategia de particionamiento y pru\u00e9bela en PostgreSQL antes de migrar los datos.<\/p>\n\n\n\n<p><strong>Tipos de \u00edndice<\/strong><br>Los \u00edndices de mapa de bits de Oracle no tienen un equivalente en PostgreSQL.<br>Identifique cada \u00edndice Bitmap en el esquema fuente y decida si un \u00edndice B-tree est\u00e1ndar, un \u00edndice parcial o un \u00edndice BRIN consigue el mismo plan de consulta.<br>No saltes este paso; los \u00edndices faltantes son una de las causas m\u00e1s comunes de problemas de rendimiento posteriores a la migraci\u00f3n.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"phase-3-data-migration\">Fase 3: Migraci\u00f3n de datos<\/h2>\n\n\n\n<p>Desactive las comprobaciones de activaci\u00f3n de FK antes de cargar, cargue en orden (DDL \u2192 datos \u2192 secuencias), restablezca cada secuencia despu\u00e9s de la carga utilizando <code>setval()<\/code>, valide los recuentos de filas para cada tabla y verifique datos en columnas de tipo DATE, num\u00e9ricas y convertidas.<br>Omitir cualquiera de estos pasos puede causar corrupci\u00f3n silenciosa de datos o fallos en la inserci\u00f3n despu\u00e9s de la puesta en marcha.<\/p>\n\n\n\n<p><strong>Desactivar las comprobaciones de disparadores de FK antes de cargar<\/strong><br>ora2pg exporta los datos de la tabla en orden alfab\u00e9tico, no en orden de dependencia de clave externa.<br>A menudo, una tabla secundaria aparece antes que su matriz en el archivo de datos, lo que provoca violaciones de FK en la carga.<br>Cargar datos dentro de una sesi\u00f3n con <code>SET session_replication_role = replica<\/code> para desactivar las comprobaciones de activaci\u00f3n de FK y, a continuaci\u00f3n, restablecer <code>DEFAULT<\/code> inmediatamente despu\u00e9s de que se complete la carga.<\/p>\n\n\n\n<p><strong>Cargar en la secuencia correcta<\/strong><br>Cargar en este orden: DDL de tablas \u2192 datos \u2192 secuencias.<br>Las tablas deben existir antes de poder cargar los datos.<br>Los datos deben cargarse antes de que se restablezcan los valores de secuencia; COPY omite por completo las secuencias, dej\u00e1ndolas en su valor INICIAL independientemente de los ID que se cargaron.<\/p>\n\n\n\n<p><strong>Restablecer secuencias despu\u00e9s de la carga de datos<\/strong><br>Despu\u00e9s de cargar los datos, cada secuencia sigue en su valor START.<br>El siguiente INSERT intentar\u00e1 utilizar un valor de secuencia que ya existe en la tabla como ID cargado.<br>Ejecutar <code>setval()<\/code> para que cada secuencia avance m\u00e1s all\u00e1 del ID con mayor carga antes de que la aplicaci\u00f3n salga en vivo.<br>El ora2pg <code>SECUENCIA<\/code> export genera este script \u2014 ejec\u00fatalo como el paso final.<\/p>\n\n\n\n<p><strong>Validar el recuento de filas para cada tabla<\/strong><br>Despu\u00e9s de la carga, compare los recuentos de filas entre Oracle y PostgreSQL para cada tabla.<br>Una discrepancia significa que un error de copia se omiti\u00f3 silenciosamente.<br>Compruebe la salida de psql para <code>ERROR<\/code> l\u00edneas durante la carga \u2014 COPY informa de los errores fila por fila y contin\u00faa por defecto.<\/p>\n\n\n\n<p><strong>Verificar datos en columnas de alto riesgo<\/strong><br>Tras validar el recuento de filas, compruebe manualmente los valores de las columnas DATE\/TIMESTAMP, las columnas num\u00e9ricas de alta precisi\u00f3n y cualquier columna que haya sido objeto de conversi\u00f3n de tipo.<br>El recuento automatizado de filas confirma la exhaustividad; las comprobaciones aleatorias confirman la correcci\u00f3n.<\/p>\n\n\n\n<blockquote class=\"wp-block-quote is-layout-flow wp-block-quote-is-layout-flow\">\n<p><strong>\u00bfEn medio de la migraci\u00f3n y no est\u00e1s seguro de haberlo cubierto todo?<\/strong><br>Ofrezco una evaluaci\u00f3n de la migraci\u00f3n con una tarifa fija que revisa el esquema, la configuraci\u00f3n y el plan de transici\u00f3n y proporciona un registro de riesgos por escrito antes de la puesta en marcha.<br><a href=\"https:\/\/rootfan.com\/es\/servicios\/\">Ver qu\u00e9 cubre la evaluaci\u00f3n<\/a><\/p>\n<\/blockquote>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"phase-4-application-changes\">Fase 4: Cambios en la aplicaci\u00f3n<\/h2>\n\n\n\n<p>Todas las construcciones SQL del dialecto de Oracle deben sustituirse: ROWNUM \u2192 LIMIT, FROM DUAL eliminado, NVL \u2192 COALESCE, DECODE \u2192 CASE, (+) outer joins \u2192 ANSI LEFT JOIN, CONNECT BY \u2192 WITH RECURSIVE, SYSDATE \u2192 NOW(), y CURRVAL sustituido por <code>lastval()<\/code> o <code>REGRESANDO<\/code>.<br>PostgreSQL rechazar\u00e1 SQL del dialecto de Oracle en tiempo de ejecuci\u00f3n \u2014 no son opcionales.<\/p>\n\n\n\n<figure class=\"wp-block-table\"><table><thead><tr><th>Oracle<\/th><th>Equivalente de PostgreSQL<\/th><\/tr><\/thead><tbody><tr><td><code>ROWNUM &lt;= n<\/code><\/td><td><code>L\u00cdMITE n<\/code><\/td><\/tr><tr><td><code>buscar s\u00f3lo las primeras n filas<\/code><\/td><td><code>buscar s\u00f3lo las primeras n filas<\/code> (ANSI, funciona en ambos)<\/td><\/tr><tr><td><code>DE DUAL<\/code><\/td><td>Quitar \u2014 usar desnudo <code>SELECCIONAR valor<\/code><\/td><\/tr><tr><td><code>NVL(a, b)<\/code><\/td><td><code>COALESCE(a, b)<\/code><\/td><\/tr><tr><td><code>DECODE(col, v1, r1, v2, r2, default)<\/code><\/td><td><code>CASO col CUANDO v1 ENTONCES r1 CUANDO v2 ENTONCES r2 SINO default FIN<\/code><\/td><\/tr><tr><td><code>col1 (+) = col2<\/code><\/td><td><code>col1 LEFT JOIN col2<\/code><\/td><\/tr><tr><td><code>CONECTAR A PRIORI<\/code><\/td><td><code>CON RECURSIVE<\/code><\/td><\/tr><tr><td><code>FECHA_SISTEMA<\/code><\/td><td><code>AHORA()<\/code> o <code>HORA_ACTUAL<\/code><\/td><\/tr><tr><td><code>VALOR ACTUAL<\/code><\/td><td><code>lastval()<\/code> o <code>DEVOLVIENDO id<\/code><\/td><\/tr><tr><td><code>ADD_MONTHS(d, n)<\/code><\/td><td><code>d + INTERVAL 'n meses'<\/code><\/td><\/tr><tr><td><code>TRUNC(fecha)<\/code><\/td><td><code>DATE_TRUNC('d\u00eda', fecha)<\/code><\/td><\/tr><\/tbody><\/table><\/figure>\n\n\n\n<p>M\u00e1s all\u00e1 de la sintaxis, compruebe las conversiones de tipo impl\u00edcitas que Oracle acepta y que PostgreSQL rechaza.<br>Oracle har\u00e1 un \"cast\" silencioso <code>'123'<\/code> a un n\u00famero en una comparaci\u00f3n num\u00e9rica.<br>PostgreSQL arrojar\u00e1 un error de no coincidencia de tipo.<br>Identif\u00edquelos en la aplicaci\u00f3n y a\u00f1ada calcos expl\u00edcitos.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"phase-5-testing\">Fase 5: Pruebas<\/h2>\n\n\n\n<p><strong>Ejecutar pruebas de regresi\u00f3n con la base de datos migrada<\/strong><br>Cada funci\u00f3n que toque el esquema migrado debe ser probada contra PostgreSQL antes del cutover.<br>Si la aplicaci\u00f3n tiene una suite de pruebas existente, ejec\u00fatala en su totalidad.<br>Si no lo hace, esta es la fase en la que la ausencia de cobertura de pruebas se vuelve costosa: las pruebas funcionales manuales son la \u00fanica alternativa.<\/p>\n\n\n\n<p><strong>Establecer una l\u00ednea de base de rendimiento antes de la transici\u00f3n<\/strong><br>Ejecute el mismo conjunto de consultas representativas tanto en Oracle como en PostgreSQL.<br>Recopilar planes de ejecuci\u00f3n de PostgreSQL utilizando <code>EXPLICAR (ANALIZAR, BUFERS)<\/code>.<br>El planificador de consultas de PostgreSQL toma decisiones diferentes a las de Oracle.<br>\u00cdndices faltantes, estad\u00edsticas desactualizadas y estrategias de uni\u00f3n incorrectas se muestran aqu\u00ed, antes de que aparezcan en producci\u00f3n.<\/p>\n\n\n\n<p><strong>Prueba con carga realista<\/strong><br>Una consulta que funciona bien de forma aislada puede comportarse de manera diferente bajo carga concurrente.<br>Realiza una prueba de carga contra PostgreSQL utilizando vol\u00famenes de datos reales o representativos antes de tomar una decisi\u00f3n de continuar o no.<br>pg_bench proporciona pruebas b\u00e1sicas de rendimiento; es preferible realizar pruebas de carga a nivel de aplicaci\u00f3n contra el esquema migrado si existe la herramienta.<\/p>\n\n\n\n<p><strong>Validaci\u00f3n de casos extremos de manipulaci\u00f3n de NULL<\/strong><br>Prueba cada consulta que filtra por NULL, insertando NULL o comparando columnas anulables.<br>Las sem\u00e1nticas de NULL son coherentes entre Oracle y PostgreSQL en SQL est\u00e1ndar, pero el c\u00f3digo de aplicaci\u00f3n escrito para el comportamiento de cadena vac\u00eda como NULL de Oracle producir\u00e1 resultados incorrectos.<\/p>\n\n\n\n<p><strong>Prueba de los ID generados por secuencias en inserciones simult\u00e1neas<\/strong><br>Ejecute inserciones concurrentes que dependan de claves primarias generadas por secuencias.<br>Verifica que no haya colisiones y que los saltos de secuencia est\u00e9n dentro de los l\u00edmites aceptables para la aplicaci\u00f3n.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"phase-6-cutover\">Fase 6: Transici\u00f3n<\/h2>\n\n\n\n<p><strong>Decida la estrategia de transici\u00f3n antes de que comience el trabajo t\u00e9cnico<\/strong><br>Hay dos opciones: transici\u00f3n de ventana de mantenimiento (la aplicaci\u00f3n se desconecta durante la transici\u00f3n) o transici\u00f3n sin tiempo de inactividad (la replicaci\u00f3n l\u00f3gica mantiene PostgreSQL sincronizado durante la transici\u00f3n).<br>La migraci\u00f3n durante la ventana de mantenimiento es m\u00e1s simple, econ\u00f3mica y confiable.<br>Para la mayor\u00eda de los sistemas internos o que no est\u00e1n de cara al consumidor, una ventana de mantenimiento de dos horas en horas valle es aceptable.<br>El corte a cero a\u00f1ade complejidad y costes significativos: util\u00edcelo s\u00f3lo cuando el SLA lo requiera realmente.<\/p>\n\n\n\n<p><strong>Escribir un plan de reversi\u00f3n<\/strong><br>Defina exactamente qu\u00e9 requiere la reversi\u00f3n a Oracle: cu\u00e1nto tiempo lleva, qui\u00e9n la ejecuta y cu\u00e1l ser\u00e1 el estado de los datos en ese momento.<br>Un plan de reversi\u00f3n que no ha sido escrito no existe.<br>Si algo sale mal despu\u00e9s de la transici\u00f3n y el equipo tiene que improvisar un desmantelamiento bajo presi\u00f3n, el resultado ser\u00e1 peor que si el plan se hubiera escrito y ensayado.<\/p>\n\n\n\n<p><strong>Criterios de aprobaci\u00f3n\/rechazo por escrito<\/strong><br>Antes de la noche de corte, acuerden por escrito las condiciones bajo las cuales proceder\u00e1 el corte y las condiciones bajo las cuales revertir\u00e1.<br>Las decisiones de \"ir\/no ir\" tomadas bajo presi\u00f3n de tiempo en medio de una ventana de mantenimiento no son fiables.<\/p>\n\n\n\n<p><strong>Hacer una simulaci\u00f3n de la migraci\u00f3n en staging<\/strong><br>Ejecuta el procedimiento completo de corte \u2014incluida la reversi\u00f3n\u2014 en un entorno de staging al menos una vez antes de la producci\u00f3n.<br>La simulaci\u00f3n de prueba sacar\u00e1 a la luz lagunas procedimentales que la preparaci\u00f3n t\u00e9cnica pas\u00f3 por alto.<\/p>\n\n\n\n<p><strong>Plan de comunicaci\u00f3n<\/strong><br>Identifique qui\u00e9n necesita ser notificado, en qu\u00e9 etapa, por qu\u00e9 canal y qui\u00e9n tiene la autoridad para aprobar el rollback.<br>Documenta eso antes de que se abra la ventana de corte.<\/p>\n\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"frequently-asked-questions\">Preguntas frecuentes<\/h2>\n\n\n<div id=\"rank-math-faq\" class=\"rank-math-block\">\n<div class=\"rank-math-list\">\n<div id=\"faq-question-1775135092634\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question\"><strong>\u00bfCu\u00e1l es el error m\u00e1s com\u00fan en una migraci\u00f3n de Oracle a PostgreSQL?<\/strong><\/h3>\n<div class=\"rank-math-answer\">\n\n<p>Mapeo de columnas Oracle DATE a PostgreSQL DATE en lugar de TIMESTAMP.<br \/>Oracle DATE almacena tanto la fecha como la hora.<br \/>PostgreSQL DATE almacena solo la fecha.<br \/>La migraci\u00f3n se completa sin errores, y cada valor de tiempo en esas columnas se establece silenciosamente a la medianoche.<br \/>Siempre mapea Oracle DATE a PostgreSQL TIMESTAMP.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1775135093634\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question\"><strong>\u00bfNecesito realizar pruebas de rendimiento antes de la migraci\u00f3n?<\/strong><\/h3>\n<div class=\"rank-math-answer\">\n\n<p>S\u00ed, siempre.<br \/>El planificador de consultas de PostgreSQL toma decisiones diferentes a las de Oracle.<br \/>Los \u00edndices que exist\u00edan en Oracle pueden no haber sido creados en PostgreSQL.<br \/>Una consulta que se ejecuta en 200 ms en Oracle puede ejecutarse en 20 segundos en PostgreSQL sin el \u00edndice adecuado.<br \/>Establezca una l\u00ednea de base de rendimiento antes de la transici\u00f3n para que no haya sorpresas el d\u00eda de la puesta en marcha.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1775135094634\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question\"><strong>\u00bfCu\u00e1l es el m\u00e9todo de transici\u00f3n m\u00e1s seguro para una base de datos Oracle de producci\u00f3n?<\/strong><\/h3>\n<div class=\"rank-math-answer\">\n\n<p>Una interrupci\u00f3n durante una ventana de mantenimiento, donde la aplicaci\u00f3n se desconecta brevemente durante el cambio, es la opci\u00f3n m\u00e1s segura para la mayor\u00eda de los sistemas.<br \/>Elimina la complejidad de mantener dos bases de datos sincronizadas y proporciona al equipo un punto de conmutaci\u00f3n limpio y determinista.<br \/>Es posible realizar una transici\u00f3n sin tiempo de inactividad mediante replicaci\u00f3n l\u00f3gica, pero a\u00f1ade costes y riesgos significativos.<br \/>\u00daselo solo cuando el SLA realmente no pueda tolerar una ventana de mantenimiento.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1775135095634\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question\"><strong>\u00bfPuedo revertir despu\u00e9s del corte si algo sale mal?<\/strong><\/h3>\n<div class=\"rank-math-answer\">\n\n<p>S\u00ed, pero solo si el plan de reversi\u00f3n se redact\u00f3 antes de que se abriera la ventana de corte.<br \/>Una reversi\u00f3n requiere que el entorno de Oracle todav\u00eda est\u00e9 intacto, que el estado de los datos se comprenda y que el procedimiento se haya ensayado.<br \/>Si ninguna de estas condiciones existe, revertir se convierte en una recuperaci\u00f3n improvisada bajo presi\u00f3n.<br \/>Siempre escribe y ensaya el procedimiento de reversi\u00f3n antes del traspaso a producci\u00f3n.<\/p>\n\n<\/div>\n<\/div>\n<div id=\"faq-question-1775135096634\" class=\"rank-math-list-item\">\n<h3 class=\"rank-math-question\"><strong>\u00bfPostgreSQL maneja NULL de la misma manera que Oracle?<\/strong><\/h3>\n<div class=\"rank-math-answer\">\n\n<p>Para la sem\u00e1ntica est\u00e1ndar de NULL de SQL \u2014 s\u00ed.<br \/>La diferencia est\u00e1 en las cadenas vac\u00edas: Oracle trata '' como NULL, PostgreSQL las trata como valores distintos.<br \/>El c\u00f3digo de la aplicaci\u00f3n que inserta '' esperando que satisfaga una restricci\u00f3n NOT NULL, o que consulta NULL esperando que coincida con cadenas vac\u00edas, se comportar\u00e1 de manera diferente en PostgreSQL.<br \/>Auditor\u00eda de este patr\u00f3n durante la fase de evaluaci\u00f3n.<\/p>\n\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n\n\n<hr class=\"wp-block-separator has-alpha-channel-opacity\"\/>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"in-summary\">En resumen<\/h2>\n\n\n\n<p>Una migraci\u00f3n de Oracle a PostgreSQL tiene \u00e9xito o falla en la preparaci\u00f3n.<br>Las herramientas son gratuitas, est\u00e1n bien documentadas y son confiables.<br>Los fallos provienen de suposiciones no comprobadas: Oracle DATE mapeado al tipo incorrecto, secuencias dejadas en su valor START, SQL de aplicaci\u00f3n que Oracle acept\u00f3 silenciosamente y PostgreSQL rechaza expl\u00edcitamente.<\/p>\n\n\n\n<p>Esta lista de comprobaci\u00f3n abarca los modos de fallo que aparecen con m\u00e1s frecuencia en las migraciones reales.<br>Trabaje fase por fase -evaluaci\u00f3n, conversi\u00f3n de esquemas, migraci\u00f3n de datos, cambios en la aplicaci\u00f3n, pruebas, transici\u00f3n- y ninguna de ellas deber\u00eda sorprenderle el d\u00eda de la puesta en marcha.<\/p>\n\n\n\n<p>Guarda esta p\u00e1gina \u2014 y si necesitas ayuda para aplicarla en producci\u00f3n, <a href=\"https:\/\/rootfan.com\/es\/servicios\/\">ponerse en contacto<\/a><\/p>","protected":false},"excerpt":{"rendered":"<p>TL;DR: Most Oracle to PostgreSQL migrations don\u2019t fail because of the tools \u2014 they fail because of skipped steps.This checklist covers every phase from pre-migration assessment through cutover: the data type traps that cause silent data loss, the sequence and NULL differences that break applications after go-live, the testing steps that get cut when timelines &hellip; <\/p>\n<p class=\"link-more\"><a href=\"https:\/\/rootfan.com\/es\/oracle-to-postgresql-migration-best-practices\/\" class=\"more-link\">Seguir leyendo<span class=\"screen-reader-text\"> &#8220;Oracle to PostgreSQL Migration Best Practices: A Checklist for DBAs and Architects&#8221;<\/span><\/a><\/p>","protected":false},"author":1,"featured_media":6656,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"rank_math_focus_keyword":"oracle to postgresql migration best practices","rank_math_title":"Oracle to PostgreSQL Migration Best Practices: A Checklist for DBAs and Architects","rank_math_description":"A phase-by-phase checklist of Oracle to PostgreSQL migration best practices \u2014 covering pre-migration assessment, schema conversion, data migration, application changes, testing, and cutover.","rank_math_robots":"","rank_math_og_title":"","rank_math_og_description":"","jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[146],"tags":[140,143,141,137,142,81],"class_list":["post-6655","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-oracle-to-postgresql","tag-audit","tag-data-migration","tag-data-types","tag-migration","tag-pl-sql","tag-step-by-step"],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/rootfan.com\/wp-content\/uploads\/pexels-photo-5674761.jpeg?fit=1880%2C1253&ssl=1","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/posts\/6655","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/comments?post=6655"}],"version-history":[{"count":12,"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/posts\/6655\/revisions"}],"predecessor-version":[{"id":6786,"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/posts\/6655\/revisions\/6786"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/media\/6656"}],"wp:attachment":[{"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/media?parent=6655"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/categories?post=6655"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/rootfan.com\/es\/wp-json\/wp\/v2\/tags?post=6655"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}