Sincronización de bases de datos entre testing y entorno de producción con git

Estoy intentando implementar git en nuestro process de desarrollo para aplicaciones php / mysql.

Hasta ahora he configurado los repositorys GIT, y estamos usando nuestras máquinas locales para las testings y estamos utilizándolo con éxito para los files, pero realmente no sé cómo manejar la database.

Hay un script cron en el server que exporta y confirma una nueva versión de la database en vivo para el repository, y he configurado un enlace posterior a la fusión en mi máquina de desarrollo para actualizar mi database local, y eso funciona bien para sincronizar la dirección producción-> testing.

No sé cómo hacer la synchronization al revés. En este momento estoy haciendo cambios en la database en el server en vivo, pero no creo que sea una buena práctica.

Entonces estoy abierto a sugerencias.

EDITAR : Hice esta pregunta, antes de entender cómo funcionan las migraciones de esquema. Ahora estoy usando django para la mayoría de mi trabajo de desarrollo web que tiene un gran module de migraciones llamado South (parte de django core desde la versión 1.7). Entonces, la mayoría de los frameworks MVC deberían tener un module de migraciones que maneje este problema.

Si desea controlar la versión de una database completa implementada en files planos, le recomiendo usar un back-end sqlite .

Si su aplicación requiere MySQL (por ejemplo, ciertos procedimientos o vistas), la versión controla los scripts de manipulación de la database (por ejemplo CREATE , ALTER ) y los scripts de población (por ejemplo, INSERT ) y los ejecuta como parte de su process de compilation. dbdeploy es un buen patrón a seguir .

Actualizar para comentar sobre su procedimiento existente
En esencia, trata su producción como la copy maestra del esquema. ¿Qué pasa si alguna vez tienes múltiples maestros? ¿Qué sucede cuando su database se vuelve demasiado grande para hacer esto de manera efectiva? ¿Qué sucede si necesita aislar un error en una versión anterior de su código? ¿Qué tan fácil es revertir a un estado de código / esquema en particular?

Hace diez años, hice esto mismo. Tenía una database pequeña, una docena de tables más o less. La aplicación ha crecido. Tiene 2000 tablas ahora. Considérame un fantasma de Christmas Future que te advierte que te alejes del dolor que he pasado.

Recomendación
En teoría, el process es fácil: hacer cambios en la database en el desarrollo, aplicarlos a la producción, hacer. La realidad es mucho más difícil. Explicaré lo que quiero decir con el ejemplo …

Eres parte de un equipo de desarrollo. Desea agregar soporte para deshabilitar counts. Además de los cambios en el código, usted decide implementar eso como un campo de bit en la database, como este:

ALTER TABLE Account ADD COLUMN disabled BIT(1) DEFAULT 0;

Ahora como mencioné anteriormente, póngalo en un file bajo control de versión, llamémoslo addDisabledColumnToAccount.sql . Usted confirma el SQL y el código cambia y los empuja.

Los otros miembros del equipo obtienen su cambio, aplican el cambio de esquema y lo testingn. Todos ustedes colectivamente deciden boost el scope original del cambio para respaldar un estado en una count, no solo deshabilitado. Entonces haces esto:

 ALTER TABLE Account DROP COLUMN disabled; ALTER TABLE Account ADD COLUMN status ENUM('active','disabled','closed') NOT NULL DEFAULT 'active'; 

y compromete tus cambios, y empuja. Todos vuelven a aplicar esto y son felices. Lo empujas dentro de tu maletero (o como marques estable) y está listo para pasar a producción.

De acuerdo. ¿Puedes detectar el problema? Hay varios. El primer gran problema es que si intenta ejecutar este script en producción, fallará. ¿Por qué? Porque la producción nunca tuvo la columna "deshabilitada" agregada.

El problema general es que las bases de datos de desarrollo atraviesan cambios provisionales que la producción no necesita / no puede atravesar. Hay muchas forms de evitar esto. La forma en que me gusta hacerlo es mantener dos pistas de scripts de cambio: desarrollo y producción. Los scripts de desarrollo son acumulativos, acrecentando cambios a medida que avanza el desarrollo: los scripts de producción representan el resultado final del desarrollo. Ambos dejan la database terminando en el mismo estado, lo que significa que sus testings finales contra la final de cualquiera deben pasar.

¿Qué otros problemas hay? Bueno, los desarrolladores pueden nombrar dos files de script de la misma manera. Por lo tanto, debe establecer un estándar que evite que los nombres de los scripts colisionen. En general, si los nombres de los scripts están asociados con algún ID de problema único, eso lo hará.

Otro problema es que cada script de cambio de esquema puede tener una versión de MySQL, una versión de SQLite, una versión de Oracle, etc. Cuantas más bases de datos admita, más cambios de esquema tendrá que manejar. Tenga esto en count al nombrar sus guiones. Algo así como addColumnToTable.mysql.sql , addColumnToTable.sqlite.sql , etc.

Finalmente, debe asegurarse de que los cambios de esquema se apliquen al mismo time que se aplica el cambio de código correspondiente. Lo que estoy diciendo es que, en general, los cambios en el código y la database van de la mano. Siempre que su tecnología de implementación le permita aplicar ambas cosas al mismo time y, lo que es más importante, revertir tanto si hay un problema , está bien. Pero ese nivel de automation puede ser difícil, y hacerlo a mano es propenso a errores.

En resumen, git lo ayudará a rastrear sus cambios y le ayudará a crear de manera cooperativa cambios en su esquema. Pero no es particularmente una herramienta de implementación, debido a las complejidades de lidiar con los cambios en el esquema a lo largo del time.

La mayoría de las bases de datos tienen instalaciones para la replicación de bases de datos. Eso me parece que es una mejor opción para la synchronization de la database que el uso de git.