Volver al blog Migration Architecture

Preparación para migraciones de bases de datos en aplicaciones autoalojadas: ¿puede revertir con seguridad?

Use esta lista de verificación para revertir migraciones de bases de datos antes de actualizar una aplicación autoalojada. Distinga la reversión del código de la recuperación de la base de datos, evalúe compatibilidad y bloqueos, verifique las copias de seguridad y defina decisiones de recuperación antes del despliegue.

Operador revisando una lista de verificación de migración de base de datos antes de desplegar una actualización de aplicación autoalojada

Por qué la reversión de la aplicación y la reversión de la base de datos son diferentes

Sustituir un contenedor de aplicación nuevo por la imagen anterior puede ser rápido. Eso es una reversión de código. No devuelve automáticamente la base de datos a la estructura y el contenido que espera la versión anterior.

Una migración de base de datos puede añadir tablas, renombrar columnas, transformar valores almacenados, crear índices, endurecer restricciones, eliminar datos o iniciar trabajo que continúa después del despliegue. Una vez que una migración se ha confirmado, un ROLLBACK a nivel de transacción ya no está disponible para ese trabajo confirmado. En su lugar, una recuperación segura puede requerir restaurar datos, repararlos o completar una corrección hacia adelante.

Trate la versión de la aplicación y el cambio de la base de datos como dos objetos de despliegue relacionados pero separados. La aprobación debe depender de si la aplicación anterior puede operar con seguridad frente al estado de la base de datos posterior a la migración, no simplemente de si hay disponible una imagen de contenedor anterior.

  • Pregunta sobre reversión de código: ¿puede iniciarse la versión anterior de la aplicación y volver a dirigir el tráfico hacia ella?
  • Pregunta sobre recuperación de la base de datos: ¿pueden restaurarse o reconstruirse el esquema anterior y los datos de negocio necesarios sin una pérdida inaceptable?
  • Pregunta sobre compatibilidad: ¿pueden coexistir el código antiguo, el código nuevo y la base de datos modificada durante la transición planificada?
  • Regla de decisión: no describa una versión como reversible hasta haber revisado tanto la ruta de código como la de base de datos.
Por qué la reversión de la aplicación y la reversión de la base de datos son diferentes

Mapee cada cambio que afecte a la base de datos antes de aprobarlo

Elabore un mapa de cambios a partir de las notas de versión de la aplicación, los archivos de migración, los scripts de despliegue y los comandos de base de datos. No se base en una etiqueta como «migración automática»; identifique qué cambia realmente esa automatización y cuándo se ejecuta.

Clasifique cada operación según su efecto en el esquema, los datos, la disponibilidad y la reversibilidad. El objetivo no es predecir cada detalle de implementación. Es exponer operaciones que cambian la estrategia de recuperación o requieren controles operativos.

En despliegues contenerizados, identifique también dónde residen los datos persistentes de la base de datos. Los volúmenes de Docker Compose son almacenes persistentes gestionados por el motor de contenedores, por lo que el volumen de la base de datos, cualquier servicio de base de datos externo y el origen de la copia de seguridad deben estar claros sin ambigüedad. Recrear una carga de trabajo de aplicación no demuestra que la base de datos se haya conservado.

  • Esquema: tablas, columnas, tipos, índices, claves foráneas, valores predeterminados y restricciones nuevos o eliminados.
  • Transformación de datos: rellenos de datos, conversiones de valores, deduplicación, cambios de cifrado, reescrituras de identificadores y eliminaciones.
  • Rendimiento y bloqueos: reescrituras de tablas, creación de índices, consultas de larga duración y operaciones que pueden esperar a otras transacciones.
  • Trabajo en segundo plano: trabajos en cola, workers, tareas programadas o tareas de inicio de la aplicación que continúan modificando datos después de la migración del esquema.
  • Dependencias: herramientas de informes, integraciones, exportaciones, vistas, consumidores de API y scripts personalizados que pueden depender de campos o valores existentes.
  • Metadatos de migración: el identificador de migración, el orden de ejecución, la herramienta o el framework y si cada paso cuenta con una operación inversa documentada.
Mapee cada cambio que afecte a la base de datos antes de aprobarlo

Compruebe explícitamente la compatibilidad hacia atrás y hacia adelante

Un despliegue seguro depende con frecuencia de una ventana de compatibilidad: un período durante el cual las versiones anterior y nueva de la aplicación pueden usar el mismo estado de base de datos. Sin esa ventana, una reversión de código después de la migración puede fallar aunque la imagen antigua se inicie normalmente.

Revise por separado los comportamientos de lectura y escritura. El código antiguo puede tolerar una nueva columna que admite valores nulos, pero fallar si se ha eliminado, renombrado, hecho obligatorio o cambiado de significado una columna en la que escribe. El código nuevo puede iniciarse antes de que termine un relleno de datos solo si puede manejar correctamente las representaciones antiguas y nuevas.

Convierta la compatibilidad en una decisión registrada, no en una suposición. Si el código antiguo no es compatible con la base de datos migrada, el plan de recuperación debe priorizar una restauración, reparación de datos o corrección hacia adelante frente a una simple reversión de código.

  • Código antiguo con esquema ampliado: ¿puede ignorar tablas, columnas e índices añadidos?
  • Código nuevo antes de que termine la migración de datos: ¿puede leer tanto formatos de valores antiguos como nuevos?
  • Código antiguo después de un relleno de datos: ¿sobrescribirá datos transformados o creará registros en un formato obsoleto?
  • Momento de aplicación de restricciones: ¿una nueva restricción NOT NULL, de unicidad o de clave foránea rechazará escrituras realizadas por una versión anterior?
  • Consumidores externos: ¿las integraciones dependen de un nombre de columna, formato de salida, identificador o comportamiento de API afectado por el cambio?
  • Operación con versiones mixtas: si varios workers de la aplicación se reinician gradualmente, ¿se admite la operación simultánea de versiones antiguas y nuevas?

Señale las operaciones destructivas y los cambios sensibles a bloqueos

Algunos cambios merecen un plan de recuperación explícito porque eliminan información, invalidan supuestos anteriores o afectan a la disponibilidad. Eliminar una columna de PostgreSQL también puede eliminar índices y restricciones de tabla que involucren esa columna; las dependencias fuera de la tabla, como claves foráneas o vistas, pueden requerir acciones adicionales. Un cambio destructivo nunca debe aprobarse solo porque aparece al final de una secuencia de migración.

Los efectos de bloqueo son igual de importantes. En PostgreSQL, los requisitos de bloqueo de ALTER TABLE varían según el subcomando, y ACCESS EXCLUSIVE es el valor predeterminado salvo que la documentación indique lo contrario. Revise las sentencias exactas en lugar de tratar todas las operaciones ALTER TABLE como equivalentes.

La creación de índices también exige una decisión de despliegue. Una creación estándar de índice en PostgreSQL bloquea las escrituras mientras se ejecuta. CREATE INDEX CONCURRENTLY evita bloquear inserciones, actualizaciones y eliminaciones simultáneas, pero no puede ejecutarse dentro de un bloque de transacción, realiza escaneos adicionales de la tabla y espera a que terminen las transacciones pertinentes. Esto modifica tanto los tiempos como la gestión de fallos.

Las formas de ALTER TABLE que reescriben tablas y TRUNCATE requieren una revisión reforzada cuando existe acceso simultáneo. PostgreSQL documenta advertencias relacionadas con MVCC para estas operaciones, incluidos casos en los que las instantáneas simultáneas pueden ver una vista vacía o incoherente después de la confirmación.

  • Destructivas: DROP COLUMN, DROP TABLE, TRUNCATE, rellenos de datos con eliminación, conversiones de valores irreversibles y sustitución de identificadores.
  • Que rompen compatibilidad: renombrar o eliminar un campo usado por código antiguo, endurecer una restricción y cambiar el significado de valores almacenados.
  • Sensibles a disponibilidad: reescrituras de tablas, operaciones ALTER TABLE con bloqueos intensivos y creaciones normales de índices en tablas con escrituras activas.
  • Pasos fuera de una única transacción: creación concurrente de índices y trabajo en segundo plano que ocurren fuera de un límite de transacción.
  • Respuesta requerida: nombre el método de recuperación exacto para cada operación señalada antes del despliegue.

Prefiera ampliar, migrar y reducir cuando la aplicación lo admita

Para cambios sustanciales, use un patrón de ampliar–migrar–reducir cuando la aplicación y las indicaciones de su proveedor lo admitan. Esto separa el trabajo de compatibilidad de la limpieza destructiva, creando margen para validar y revertir código antes de introducir cambios irreversibles.

Ampliar significa añadir estructuras nuevas sin eliminar las antiguas: por ejemplo, un nuevo campo que admite valores nulos, una tabla o un índice. Migrar significa rellenar datos y enseñar a la nueva versión de la aplicación a leer y escribir la representación compatible. Reducir significa eliminar estructuras obsoletas solo después de que haya terminado la ventana de compatibilidad y se haya completado la validación.

No fuerce este patrón sobre una aplicación cuya ruta de migración proporcionada no admita versiones escalonadas. En ese caso, documente la secuencia exigida por el proveedor, pruébela fielmente y elija un plan adecuado de mantenimiento y recuperación. El principio útil es separar el riesgo, no reescribir artificialmente migraciones de terceros.

  • Ampliar: añada la nueva estructura y confirme que el código antiguo continúa funcionando.
  • Desplegar código compatible: asegúrese de que el código nuevo maneja ambas representaciones cuando sea necesario.
  • Migrar: ejecute rellenos de datos en lotes observables cuando la aplicación admita ese enfoque.
  • Validar: compare recuentos, registros necesarios, permisos, integraciones y flujos de trabajo clave.
  • Reducir: elimine campos o formatos heredados solo después de que la ventana de reversión se haya cerrado intencionadamente.
  • Registre el punto de no retorno: indique exactamente cuándo una simple reversión de código deja de ser segura.

Recopile evidencia de despliegue, no solo el estado de una copia de seguridad

Una copia de seguridad solo es útil cuando se conocen su método, cobertura, ubicación y proceso de restauración. PostgreSQL distingue entre volcados SQL, copias de seguridad del sistema de archivos y archivado continuo; cada uno tiene fortalezas y limitaciones diferentes. Registre qué método protege este cambio en vez de usar la afirmación genérica «copia de seguridad completada».

Un volcado lógico de PostgreSQL es una instantánea internamente coherente desde el momento en que comienza pg_dump, pero las operaciones que requieren un bloqueo exclusivo, incluida la mayoría de las formas de ALTER TABLE, son excepciones a su comportamiento, por lo demás no bloqueante. Confirme que el momento y el método de la copia de seguridad son compatibles con los requisitos de bloqueo y recuperación de la migración.

La recuperación a un punto en el tiempo no es una promesa genérica. En PostgreSQL, requiere una copia de seguridad física previa adecuada y registros de escritura anticipada archivados que cubran el momento objetivo. Si faltan estos requisitos previos, no incluya la recuperación a un punto en el tiempo como opción disponible.

Airbip proporciona copias de seguridad diarias, semanales y mensuales configurables para despliegues de aplicaciones. Los equipos deben aun así verificar el alcance, la configuración de retención, la cobertura de la base de datos y el procedimiento de restauración aplicables a su propia instancia antes de depender de esas copias para una decisión de migración.

  • Identidad de la copia de seguridad: método, hora de finalización, alcance, ubicación de almacenamiento y la persona que la verificó.
  • Confianza en la restauración: una prueba de restauración reciente, pasos estimados, credenciales necesarias, entorno de destino y limitaciones conocidas.
  • Evidencia de migración: versión exacta de la aplicación o referencia de imagen, identificadores de migración, horas de inicio y finalización, registros y errores.
  • Comprobaciones de referencia: registre recuentos importantes, registros representativos, flujos de trabajo críticos y estado de integraciones antes del cambio.
  • Comprobaciones posteriores al cambio: registre las mismas comprobaciones después de la migración y defina diferencias aceptables.
  • Umbral de recuperación: decida el tiempo máximo de interrupción y la exposición a pérdida de datos aceptables antes de comenzar.

Decida si se requiere una ventana de mantenimiento o una restricción temporal de escritura

Una ventana de mantenimiento está justificada cuando la migración puede bloquear escrituras, crear estados mixtos incompatibles, durar un tiempo incierto o requerir una restauración que no pueda fusionar de forma segura los cambios posteriores de usuarios. Una restricción temporal de escritura puede ser suficiente cuando las lecturas siguen siendo seguras, pero las escrituras entrarían en conflicto con un relleno de datos, un cambio de esquema o una posible reversión.

Base la decisión en las operaciones reales y el impacto en el negocio. Por ejemplo, una creación normal de índice en PostgreSQL bloquea escrituras, mientras que una creación concurrente de índice evita ese bloqueo concreto de escrituras, pero presenta características operativas de mayor duración y no puede compartir un límite de transacción normal. Ninguna opción es automáticamente más segura sin considerar carga de trabajo, tiempos y recuperación.

Defina qué verán los usuarios y qué harán los operadores. Una restricción de escritura puede significar pausar workers en segundo plano, desactivar importaciones programadas, poner una aplicación en un modo de mantenimiento admitido por el proveedor o rechazar temporalmente solicitudes de escritura. Asegúrese de que las integraciones y los administradores reciban la misma instrucción; de lo contrario, podrían crear datos que compliquen la recuperación.

  • Use una ventana de mantenimiento completa cuando los cambios de esquema o la restauración hagan inseguras las escrituras simultáneas.
  • Use una restricción de escritura específica cuando el acceso de lectura pueda continuar con seguridad y la aplicación admita ese modo.
  • Pause o tenga en cuenta los workers en segundo plano, importaciones, webhooks y trabajos programados.
  • Establezca una hora de inicio, duración esperada, punto de decisión para ampliar y vía de comunicación con los usuarios.
  • Confirme cómo se reanudarán, deduplicarán o conciliarán los trabajos en cola después del despliegue o la recuperación.
  • Deténgase si los bloqueos, la duración o las tasas de error superan el umbral aprobado.

Elija la ruta de recuperación antes de desplegar

La recuperación es un árbol de decisiones, no un único botón de reversión. Apruebe previamente las condiciones en las que el equipo revertirá el código de aplicación, restaurará datos, reparará un conjunto limitado de registros o continuará con una corrección hacia adelante. Designe quién puede autorizar cada acción, especialmente una restauración que puede descartar escrituras legítimas realizadas después del punto de copia de seguridad seleccionado.

Una reversión de código es apropiada solo cuando se ha confirmado la compatibilidad y la migración no ha creado un estado de base de datos inseguro para la versión anterior. Una restauración es apropiada cuando el estado de los datos debe volver a un punto conocido, pero requiere tratar cuidadosamente las escrituras ocurridas después de la copia de seguridad. La reparación de datos puede funcionar para un error pequeño, plenamente comprendido y auditable. Una corrección hacia adelante suele ser más segura cuando una restauración perdería más actividad de negocio válida que la que perdería al corregir el defecto.

El comportamiento del framework también importa. Por ejemplo, Django identifica los pasos RunPython sin reverse_code y los pasos RunSQL sin reverse_sql como irreversibles. El comportamiento de las transacciones de migración de Django también varía según el motor de base de datos: su gestión predeterminada difiere entre motores con transacciones DDL, como PostgreSQL y SQLite, y motores como MySQL y Oracle. Lea la guía del framework de migración de la aplicación y la específica de la base de datos antes de suponer que la reversión está disponible.

  • Reversión de código: especifique la versión anterior compatible y las comprobaciones necesarias antes de redirigir el tráfico.
  • Restauración: especifique el punto de recuperación, método, tiempo de inactividad esperado, implicaciones de pérdida de datos y responsable de conciliación.
  • Reparación de datos: especifique los registros afectados, script de reparación, rastro de auditoría, consulta de validación y método de reversión para la propia reparación.
  • Corrección hacia adelante: especifique el estado intermedio seguro, responsable, vía de escalado y controles de impacto para los usuarios.
  • Autoridad: nombre al operador técnico, al responsable de datos de negocio y al responsable final de decisión para cada opción de recuperación.
  • Comunicaciones: prepare mensajes internos y dirigidos a usuarios para mantenimiento prolongado, conciliación de datos o restauración del servicio.

Preguntas frecuentes

¿Puedo revertir una migración de base de datos revirtiendo el contenedor de la aplicación?

No necesariamente. Volver a una imagen de aplicación anterior cambia el código, no el esquema ni los datos de la base de datos ya confirmados. Use la reversión de código solo después de confirmar que la versión anterior es compatible con el estado de la base de datos posterior a la migración.

¿Qué debe incluir una lista de verificación para revertir migraciones de bases de datos?

Incluya los cambios exactos de esquema y datos, la reversibilidad de la migración, la compatibilidad del código antiguo y nuevo, los riesgos de bloqueos y tiempo de inactividad, el método y alcance de las copias de seguridad, evidencia de pruebas de restauración, validación antes y después del cambio, un plan de control de escrituras, opciones de recuperación y responsables de decisión designados.

¿Cuándo no basta una copia de seguridad para una reversión segura?

Una copia de seguridad por sí sola es insuficiente cuando el equipo no sabe si incluye la base de datos, si puede restaurarse, qué momento en el tiempo representa o cómo se tratarán los cambios de usuarios posteriores a la copia. Un plan de restauración necesita tanto evidencia como una decisión de negocio sobre la pérdida de datos aceptable.

¿CREATE INDEX CONCURRENTLY es siempre la opción adecuada en PostgreSQL?

No. Evita bloquear inserciones, actualizaciones y eliminaciones simultáneas, pero no puede ejecutarse dentro de un bloque de transacción, usa escaneos adicionales de tabla y espera a las transacciones pertinentes. Elíjalo según la carga de trabajo, las herramientas de despliegue, la duración y la gestión de fallos.

¿Cuándo debemos usar una ventana de mantenimiento para una migración de base de datos?

Úsela cuando las operaciones puedan bloquear escrituras, cuando las versiones antigua y nueva de la aplicación no puedan coexistir con seguridad, cuando la actividad en segundo plano complique la recuperación o cuando una restauración sea la respuesta probable ante un fallo. Una restricción temporal de escritura puede ser suficiente para cambios de menor impacto cuando las lecturas puedan continuar con seguridad.

¿Cómo encaja Airbip en la preparación para migraciones de bases de datos?

Airbip gestiona despliegues de aplicaciones basados en Docker y ofrece copias de seguridad diarias, semanales y mensuales configurables. La preparación para migraciones sigue siendo una responsabilidad operativa compartida: el equipo debe verificar qué se respalda, probar la restauración cuando corresponda, comprender el comportamiento de migración de la aplicación y aprobar las decisiones sobre datos y recuperación.

Fuentes y lecturas adicionales

  1. PostgreSQL transactions — PostgreSQL Global Development Group
  2. PostgreSQL ALTER TABLE — PostgreSQL Global Development Group
  3. PostgreSQL CREATE INDEX — PostgreSQL Global Development Group
  4. PostgreSQL backup and restore — PostgreSQL Global Development Group
  5. PostgreSQL SQL dump — PostgreSQL Global Development Group
  6. PostgreSQL write-ahead logging — PostgreSQL Global Development Group
  7. PostgreSQL MVCC caveats — PostgreSQL Global Development Group
  8. Django migration operations — Django Software Foundation
  9. Django migrations — Django Software Foundation
  10. Docker Compose volume reference — Docker