
En el mundo de PHP, las herramientas de migraci贸n de estructura de base de datos son bien conocidas:
Doctrine ,
Phinx de CakePHP, de
Laravel , de
Yii , esto es lo primero que se me ocurri贸. Seguramente hay una docena m谩s. Y la mayor铆a de ellos trabajan con migraciones: comandos para realizar cambios incrementales en el esquema de la base de datos.
No describir茅 por qu茅 esto es as铆, hay muchas publicaciones sobre este tema en Habr茅. Por ejemplo:
Adem谩s, el desarrollo de mi
experiencia como equipo con un cambio constante en la estructura de la base de datos en diferentes ramas.
SQL sin formato vs PHP api
Escribimos migraciones en SQL puro. Muchas herramientas proporcionan API de PHP para escribir instrucciones traducidas al c贸digo SQL. Ahora no entiendo por qu茅 es esto. Dicha herramienta siempre estar谩 limitada en sus capacidades. No permiten escribir instrucciones espec铆ficas para un motor espec铆fico; a煤n debe usar SQL puro. No estoy hablando de escribir procedimientos y puntos de vista.
Alguien se quej贸 de que no quer铆a aprender la sintaxis de los comandos ALTER ... Bueno, no s茅, abr铆 el directorio y escrib铆 ejemplos de la monta帽a, especialmente en un gran proyecto.
Las migraciones de datos (INSERT, UPDATE) tambi茅n se escriben siempre en SQL. Porque nunca puede confiar en la versi贸n actual de ORM y Modelos. En una revisi贸n son, en la otra ya no.
Por ejemplo:
Rollback Country::delete()->where(....)->execute();
Quiere revertir el estado de la base de datos. Y esta clase de PHP ya no est谩 en el repositorio. Debes buscar el 煤ltimo commit donde estuvo y retroceder desde all铆. Brrr ...
Por lo tanto, SQL es simple y confiable:
Transacciones en DDL
Con la transici贸n a PostgreSQL, me olvid茅 de las migraciones rotas como una pesadilla: la migraci贸n cay贸 en el medio, algo enrollado, algo que no est谩 all铆, sentarse y editar los bol铆grafos ... Esto nos oblig贸 a escribir comandos at贸micos de una sola l铆nea y ejecutarlos uno por uno. Todo es simple con las transacciones: si algo se rompe, todo retrocede (bueno, casi todo))). Simplemente arr茅glalo y rein铆cialo. El ensamblaje autom谩tico funciona con una explosi贸n, si algo cae, se arregla y sube r谩pidamente.
Vistas (vistas) y funciones
El problema aqu铆 es que no se pueden actualizar de forma incremental, como ALTERAR en las tablas. Necesita GOTAR y CREAR. Es decir sobre el diferencial (texto de migraci贸n) no est谩 del todo claro qu茅 cambi贸 al final. Especialmente cuando la l贸gica est谩 torcida, es bastante inconveniente. Por ejemplo:
驴Qu茅 ha cambiado aqu铆?
Nos detuvimos ante el hecho de que al lado de las migraciones hay un pap谩, donde se almacena el c贸digo de vista y procedimiento actual, que se actualiza y copia en la migraci贸n de reversi贸n.
Y ahora la diferencia se convierte en:

De vuelta en Avito, creamos una soluci贸n interesante para
versionar el c贸digo de procedimiento almacenado.En general, este caso plantea un buen problema: c贸mo ver el historial de cambios en un objeto particular de la estructura de la base de datos. Para cada tabla, quiero ver el historial de cambios en relaci贸n con la soluci贸n de tareas espec铆ficas.

En Habr茅 se encontr贸 un
enfoque interesante para la automatizaci贸n de la fijaci贸n de cambios en la estructura de la base de datos.
Trabajar con ramas
Mi dolor eterno es c贸mo cambiar entre dos ramas A y B, cada una de las cuales tiene ediciones en la estructura de la base de datos.

Es necesario revertir las migraciones en la rama A (tambi茅n debemos recordar cu谩l y cu谩ntas), luego cambiar a la rama B y rodar nuevas migraciones. De acuerdo, si nuestras ediciones son compatibles y puedo cambiar a la segunda rama y realizar migraciones adicionales desde B.
Y si no? 驴Y si tengo m谩s de una rama? Y luego revertir todos estos estado de revisi贸n? Siempre lo odi茅 ...
Ahora, al cambiar a la sucursal de otra persona, puedo eliminar autom谩ticamente las migraciones de otras personas y pasar las actuales:

donde:
D : migraciones A que se iniciaron en la rama A, pero que no est谩n en la rama actual, y se recomienda eliminarlas
A - B-migraciones que aparecieron en la nueva sucursal y necesitan ser rodadas
Se vuelve incre铆blemente conveniente al probar y ensamblar autom谩ticamente en una base. Cuando no hay sentido u oportunidad para que cada rama cree una base desde cero. Cambie a la rama y sincronice autom谩ticamente el estado de la base de datos.
Numeraci贸n y orden de ejecuci贸n.
Todas las herramientas que conozco son migraciones estampadas cronometradas es una buena soluci贸n. Si escribo varias migraciones, se conserva la secuencia necesaria. Otro desarrollador puede tener cualquier fecha en otro hilo, incluso el m铆o, pero no importa en qu茅 orden lo hagamos, nuestros cambios son independientes entre s铆. Incluso si trabajamos con la misma tabla (agregar por columna), todos los cambios necesarios tendr谩n lugar en cualquier orden. Lo principal es que se respeta la secuencia de mis ediciones dependientes.

No considero casos en los que necesitamos editar lo mismo: estos puntos siempre son consistentes. Bueno, o habr谩 un fallo en la etapa de montaje y prueba.
Aqu铆 hay un ejemplo interesante.
Realizamos diferentes ediciones en una vista o procedimiento, es decir en aquellas estructuras que se actualizan mediante eliminaci贸n. Es decir Por ejemplo, agregu茅 la columna col_A a la vista y mi colega col_B. En consecuencia, si su c贸digo se implementa despu茅s del m铆o, entonces su columna no tendr谩 mi columna:
CREATE VIEW vusers AS SELECT login, name,
rama-A | rama-B |
---|
DROP VIEW vusers; CREATE VIEW vusers AS SELECT login, name, col_A, | DROP VIEW vusers; CREATE VIEW vusers AS SELECT login, name, col_B, |
En este caso, una rama debe hacerse dependiente de otra.
Otro caso interesante son las correcciones en las migraciones.
La conclusi贸n es que la migraci贸n que se aplic贸 ya no se volver谩 a aplicar, sin importar cu谩ntos cambios se realicen (primero debe retroceder y luego volver a aplicarla). Es decir Enviaste Migration para probar, todas las reglas, y luego te diste cuenta e hiciste una peque帽a edici贸n. Pero la prueba u otro servidor donde lo us贸 no lo sabr谩n.
En estos casos, cambiamos el nombre del archivo de migraci贸n, agregando un nuevo n煤mero de versi贸n, para que el migrador comience a interpretar esto como 2 comandos: retroceder 1 y retroceder 2,
por ejemplo:

Rollback
Siempre escriba ROLLBACK, incluso si no puede devolver la base a su estado original. Por ejemplo, DROP TABLE, 驴qu茅 tipo de ROLLBACK puede ser?
En tales casos, escribimos una CREAR TABLA vac铆a. La conclusi贸n es que el sistema de desarrollo siempre puede cambiar f谩cilmente entre ramas. Para PROD, la gesti贸n de revisi贸n irreversible ya est谩 decidida a un nivel diferente. Puedo hacer una copia de la tabla o cambiarle el nombre en lugar de eliminarla. Pero el principio de la migraci贸n de escritura: la reversi贸n est谩 OBLIGADA a devolver la ESTRUCTURA de la base al nivel inicial, y los datos ya son posibles.
En un ambiente de combate, us茅 una reversi贸n solo 1-2 veces en mi vida. Y en desarrollo todo el tiempo. Por lo tanto, siempre verifico que la reversi贸n devuelva todo al estado deseado.
A menudo, los desarrolladores pueden cometer errores en la reversi贸n. Porque se concentran principalmente en nuevas ediciones, se prueban y trabajan con ellas. Otras personas y procesos ya est谩n trabajando con la reversi贸n. Por lo tanto, siempre pruebo las migraciones UP - ROLLBACK - UP
Aparece un punto interesante en una base de prueba permanente (la base de datos no se elimina). Escribieron una migraci贸n, la reversi贸n funciona bien, la enviaron para probar, el probador gener贸 datos en un nuevo formato, intenta revertir, pero no dan datos nuevos. Ejemplo cl谩sico
ALTER TABLE abc ALTER COLUMN code SET NULL
Genial Despu茅s de la prueba, la base de datos est谩 llena de valores NULL. Hacer ROLLBACK:
ALTER TABLE abc ALTER COLUMN code SET NOT NULL
y viceversa :-(
Necesita agregar el comando:
DELETE FROM abc WHERE code IS NULL
La dificultad es que debe tener esto en cuenta y no automatizarlo si no estamos hablando de volver a crear la base de datos desde cero cada vez.
Un poco sobre la eliminaci贸n de datos
Por lo general, tratamos de NO eliminar tablas y columnas rellenas a la vez. Es mejor cambiar el nombre o hacer una copia y eliminarla m谩s tarde, cuando todo se estabilice y los datos pierdan relevancia:
ALTER TABLE user_logs RENAME TO user_logs_20190223;
Migrador
Ahora estamos trabajando con Laravel: tiene un motor de gesti贸n de migraci贸n est谩ndar y familiar. Si lo desea, escriba incluso en SQL puro, aunque todav铆a est谩 en la clase PHP. Pero mis repetidos intentos de hacerlo funcionar de la manera que necesit谩bamos resultaron en un repositorio separado:
- La soluci贸n consta de 2 partes: lib e implementaci贸n para una consola espec铆fica (Laravel, Symfony). Puede integrarse en cualquier consola, o al menos en el bozal web.
- No hay configuraci贸n ni conexi贸n: por qu茅, cuando ya est谩 en su proyecto. Aferra tu conexi贸n a la interfaz y listo.
- La reversi贸n de SQL se almacena en la base de datos. Esto es necesario para cambiar entre ramas.
- Probado en Postgesql, Mysql (sin transacciones). Es adecuado en principio para cualquier base y estructura, porque se utiliza el formato sin formato.
Referencias
-
migrations-lib-
implementaci贸n bajo Laravel / Artisan-
implementaci贸n bajo Symfony / Console