Mecanismos para el seguimiento de cambios en el esquema de la base de datos [cerrado]

135

¿Cuáles son los mejores métodos para rastrear y / o automatizar cambios en el esquema de DB? Nuestro equipo usa Subversion para el control de versiones y hemos podido automatizar algunas de nuestras tareas de esta manera (empujando las compilaciones a un servidor intermedio, implementando código probado en un servidor de producción) pero aún estamos haciendo actualizaciones de la base de datos manualmente. Me gustaría encontrar o crear una solución que nos permita trabajar de manera eficiente en servidores con diferentes entornos mientras continúo usando Subversion como un back-end a través del cual se envían actualizaciones de código y DB a varios servidores.

Muchos paquetes de software populares incluyen scripts de actualización automática que detectan la versión DB y aplican los cambios necesarios. ¿Es esta la mejor manera de hacerlo incluso a mayor escala (en múltiples proyectos y, a veces, en múltiples entornos e idiomas)? Si es así, ¿hay algún código existente que simplifique el proceso o es mejor simplemente lanzar nuestra propia solución? ¿Alguien ha implementado algo similar antes y lo ha integrado en los ganchos posteriores a la confirmación de Subversion, o es una mala idea?

Si bien sería preferible una solución que admita múltiples plataformas, definitivamente debemos admitir la pila Linux / Apache / MySQL / PHP, ya que la mayoría de nuestro trabajo está en esa plataforma.

pix0r
fuente

Respuestas:

56

En el mundo de Rails, existe el concepto de migraciones, scripts en los que se realizan cambios en la base de datos en Ruby en lugar de una versión de SQL específica de la base de datos. Su código de migración de Ruby termina convirtiéndose en el DDL específico de su base de datos actual; Esto hace que cambiar de plataforma de base de datos sea muy fácil.

Por cada cambio que realice en la base de datos, debe escribir una nueva migración. Las migraciones suelen tener dos métodos: un método "arriba" en el que se aplican los cambios y un método "abajo" en el que se deshacen los cambios. Un solo comando actualiza la base de datos y también puede usarse para llevar la base de datos a una versión específica del esquema. En Rails, las migraciones se mantienen en su propio directorio en el directorio del proyecto y se registran en el control de versiones como cualquier otro código de proyecto.

Esta guía de Oracle para las migraciones de Rails cubre bastante bien las migraciones.

Los desarrolladores que usan otros idiomas han analizado las migraciones y han implementado sus propias versiones específicas del idioma. Sé de Ruckusing , un sistema de migraciones PHP modelado a partir de las migraciones de Rails; Puede ser lo que estás buscando.

Joey deVilla
fuente
1
Ruckusing FTW: lo adaptamos a nuestro sistema db y estamos muy contentos con él.
Piskvor salió del edificio el
Ahora se encuentra en github: github.com/ruckus/ruckusing-migrations
50

Utilizamos algo similar a bcwoord para mantener nuestros esquemas de base de datos sincronizados en 5 instalaciones diferentes (producción, puesta en escena y algunas instalaciones de desarrollo), y respaldados en el control de versiones, y funciona bastante bien. Voy a elaborar un poco:


Para sincronizar la estructura de la base de datos, tenemos un solo script, update.php, y varios archivos numerados 1.sql, 2.sql, 3.sql, etc. El script usa una tabla adicional para almacenar el número de versión actual del base de datos. Los archivos N.sql están diseñados a mano, para pasar de la versión (N-1) a la versión N de la base de datos.

Se pueden usar para agregar tablas, agregar columnas, migrar datos de un formato de columna antiguo a uno nuevo y luego soltar la columna, insertar filas de datos "maestros" como tipos de usuario, etc. Básicamente, puede hacer cualquier cosa y con los datos adecuados guiones de migración que nunca perderá datos.

El script de actualización funciona así:

  • Conéctese a la base de datos.
  • Haga una copia de seguridad de la base de datos actual (porque las cosas saldrán mal) [mysqldump].
  • Cree una tabla de contabilidad (llamada _meta) si no existe.
  • Lea la VERSIÓN actual de la tabla _meta. Suponga 0 si no se encuentra.
  • Para todos los archivos .sql con un número superior a VERSION, ejecútelos en orden
  • Si uno de los archivos produjo un error: regrese a la copia de seguridad
  • De lo contrario, actualice la versión en la tabla de contabilidad al archivo .sql más alto ejecutado.

Todo pasa al control de la fuente, y cada instalación tiene un script para actualizar a la última versión con una sola ejecución del script (llamando a update.php con la contraseña de la base de datos adecuada, etc.). Actualizamos los entornos de producción y puesta en escena de SVN a través de un script que llama automáticamente al script de actualización de la base de datos, por lo que una actualización de código viene con las actualizaciones necesarias de la base de datos.

También podemos usar el mismo script para recrear toda la base de datos desde cero; simplemente soltamos y recreamos la base de datos, luego ejecutamos el script que repoblará completamente la base de datos. También podemos usar el script para llenar una base de datos vacía para pruebas automatizadas.


Tomó solo unas pocas horas configurar este sistema, es conceptualmente simple y todos obtienen el esquema de numeración de versiones, y ha sido invaluable para tener la capacidad de avanzar y evolucionar el diseño de la base de datos, sin tener que comunicar o ejecutar manualmente las modificaciones. en todas las bases de datos.

Sin embargo, ¡tenga cuidado al pegar consultas de phpMyAdmin! Esas consultas generadas generalmente incluyen el nombre de la base de datos, que definitivamente no desea, ya que romperá sus scripts. Algo así como CREATE TABLE mydb. newtable(...) fallará si la base de datos en el sistema no se llama mydb. Creamos un enlace SVN previo al comentario que no permitirá los archivos .sql que contengan la mydbcadena, lo cual es una señal segura de que alguien copió / pegó de phpMyAdmin sin una verificación adecuada.

rix0rrr
fuente
¿Cómo manejaste las colisiones? ¿Múltiples desarrolladores que cambian el mismo elemento en la base de datos, por ejemplo, un procedimiento almacenado? Esto puede suceder si está trabajando en la misma rama o si tiene dos líneas de desarrollo en marcha (dos ramas)
Asaf Mesika
Las colisiones fueron muy raras; lo único que sucedió realmente es que dos personas intentarían crear el mismo archivo N.sql. Por supuesto, el primero gana y el segundo se ve obligado a cambiar el nombre al siguiente número más alto e intentar nuevamente. Sin embargo, no teníamos la versión de la base de datos en una rama.
rix0rrr
12

Mi equipo escribe todos los cambios en la base de datos y los confirma en SVN, junto con cada lanzamiento de la aplicación. Esto permite cambios incrementales de la base de datos, sin perder ningún dato.

Para pasar de una versión a la siguiente, solo necesita ejecutar el conjunto de scripts de cambio, y su base de datos está actualizada y todavía tiene todos sus datos. Puede que no sea el método más fácil, pero definitivamente es efectivo.

Brandon Wood
fuente
1
¿Cómo escribes todos los cambios?
Smith
10

El problema aquí es realmente facilitar a los desarrolladores la escritura de sus propios cambios locales en el control de origen para compartirlos con el equipo. Enfrenté este problema durante muchos años y me inspiró la funcionalidad de Visual Studio para profesionales de bases de datos. Si desea una herramienta de código abierto con las mismas características, intente esto: http://dbsourcetools.codeplex.com/ Diviértase, - Nathan.


fuente
10

Si todavía está buscando soluciones: estamos proponiendo una herramienta llamada neXtep designer. Es un entorno de desarrollo de base de datos con el que puede poner toda su base de datos bajo control de versiones. Trabaja en un repositorio de versión controlada donde se puede rastrear cada cambio.

Cuando necesite lanzar una actualización, puede confirmar sus componentes y el producto generará automáticamente el script de actualización SQL de la versión anterior. Por supuesto, puede generar este SQL a partir de 2 versiones.

Entonces tiene muchas opciones: puede tomar esos scripts y ponerlos en su SVN con el código de su aplicación para que su mecanismo existente lo implemente. Otra opción es utilizar el mecanismo de entrega de neXtep: los scripts se exportan en algo llamado "paquete de entrega" (scripts SQL + descriptor XML), y un instalador puede comprender este paquete y desplegarlo en un servidor de destino a la vez que garantiza la consistencia y dependencia de la estructura. verificar, registrar la versión instalada, etc.

El producto es GPL y está basado en Eclipse, por lo que se ejecuta en Linux, Mac y Windows. También es compatible con Oracle, Mysql y Postgresql en este momento (el soporte de DB2 está en camino). Eche un vistazo a la wiki donde encontrará información más detallada: http://www.nextep-softwares.com/wiki

Christophe Fondacci
fuente
Parece interesante. ¿Tiene también una interfaz de línea de comandos o está planeada?
Piskvor salió del edificio el
8

Scott Ambler produce una gran serie de artículos (y es coautor de un libro ) sobre refactorización de bases de datos, con la idea de que esencialmente debe aplicar los principios y prácticas de TDD para mantener su esquema. Configura una serie de estructura y pruebas de unidad de datos semilla para la base de datos. Luego, antes de cambiar cualquier cosa, modifica / escribe pruebas para reflejar ese cambio.

Hemos estado haciendo esto por un tiempo y parece funcionar. Escribimos código para generar comprobaciones básicas de nombre de columna y tipo de datos en un conjunto de pruebas unitarias. Podemos volver a ejecutar esas pruebas en cualquier momento para verificar que la base de datos en la comprobación de SVN coincida con la base de datos en vivo que la aplicación realmente está ejecutando.

Como resultado, los desarrolladores también a veces modifican su base de datos de sandbox y no actualizan el archivo de esquema en SVN. El código entonces depende de un cambio de base de datos que no se ha registrado. Ese tipo de error puede ser terriblemente difícil de precisar, pero el conjunto de pruebas lo detectará de inmediato. Esto es particularmente bueno si lo tiene integrado en un plan de integración continua más grande.

Sam McAfee
fuente
7

Vuelque su esquema en un archivo y agréguelo al control de origen. Luego, un simple diff le mostrará lo que cambió.

programador muerto
fuente
1
El volcado tiene que estar en SQL, como un mysqldump, los volcados de Oracle son binarios.
Osama Al-Maadeed
77
También hay un problema más fundamental con la diferencia de esquema. ¿Cómo diferenciar una columna soltar + agregar de un cambio de nombre de columna? La respuesta es simple: no puedes. Esta es la razón por la que necesita registrar las operaciones reales de cambio de esquema.
psp
El diff mostrará que una columna se ha ido, mientras que la otra apareció (a menos que tengan el mismo nombre), y la mayoría de las veces es suficiente. Crear un script para cada cambio de esquema es una buena manera de hacerlo, por supuesto: en Drupal esto se maneja mediante un enlace especial, por ejemplo.
deadprogrammer
5

Es un poco de baja tecnología, y puede haber una mejor solución, pero podría almacenar su esquema en un script SQL que se puede ejecutar para crear la base de datos. Creo que puede ejecutar un comando para generar este script, pero desafortunadamente no lo sé.

Luego, confirme el script en el control de origen junto con el código que funciona en él. Cuando necesite cambiar el esquema junto con el código, el script puede registrarse junto con el código que requiere el esquema cambiado. Luego, diffs en el script indicará diffs en los cambios de esquema.

Con este script, puede integrarlo con DBUnit o algún tipo de script de compilación, por lo que parece que podría encajar con sus procesos ya automatizados.

Mike Stone
fuente
Sí, eso es más o menos lo que tenemos en este momento. Desafortunadamente, eso no nos da una manera fácil de modificar las bases de datos existentes: el script SQL generado por mysqldump supone que está creando la tabla desde cero (o sobrescribiendo una tabla si existe). Necesitamos algo un poco más de alta tecnología porque necesita aplicar una secuencia de sentencias ALTER TABLE a la base de datos, y para hacerlo correctamente, debe conocer el estado actual de la base de datos.
pix0r
5

Si está utilizando C #, eche un vistazo a Subsonic, una herramienta ORM muy útil, pero también genera un script sql para recrear su esquema y \ o datos. Estas secuencias de comandos se pueden poner en el control de origen.

http://subsonicproject.com/

Dan
fuente
Parece ser una URL muerta a partir de este momento.
Mark Schultheiss
5

Utilicé la siguiente estructura de proyecto de base de datos en Visual Studio para varios proyectos y funcionó bastante bien:

Base de datos

Cambiar guiones

0.PreDeploy.sql

1.SchemaChanges.sql

2.DataChanges.sql

3.Permissions.sql

Crear guiones

Sprocs

Las funciones

Puntos de vista

Nuestro sistema de compilación luego actualiza la base de datos de una versión a la siguiente ejecutando los scripts en el siguiente orden:

1.PreDeploy.sql

2.SchemaChanges.sql

Contenido de la carpeta Crear secuencias de comandos

2.DataChanges.sql

3.Permissions.sql

Cada desarrollador verifica en sus cambios un error / característica particular agregando su código al final de cada archivo. Una vez que se completa una versión principal y se ramifica en el control de origen, se elimina el contenido de los archivos .sql en la carpeta Cambiar secuencias de comandos.

tbreffni
fuente
5

Utilizamos una solución muy simple pero efectiva.

Para nuevas instalaciones, tenemos un archivo metadata.sql en el repositorio que contiene todo el esquema de base de datos, luego, en el proceso de compilación, usamos este archivo para generar la base de datos.

Para las actualizaciones, agregamos las actualizaciones en el software codificado. Lo mantenemos codificado porque no nos gusta resolver problemas antes de que realmente ES un problema, y ​​este tipo de cosas hasta ahora no han demostrado ser un problema.

Entonces en nuestro software tenemos algo como esto:

RegisterUpgrade(1, 'ALTER TABLE XX ADD XY CHAR(1) NOT NULL;');

Este código verificará si la base de datos está en la versión 1 (que se almacena en una tabla creada automáticamente), si está desactualizada, se ejecuta el comando.

Para actualizar metadata.sql en el repositorio, ejecutamos estas actualizaciones localmente y luego extraemos los metadatos de la base de datos completa.

Lo único que sucede de vez en cuando, es olvidar comprometer metadata.sql, pero este no es un problema importante porque es fácil de probar en el proceso de compilación y también lo único que podría suceder es hacer una nueva instalación con una base de datos desactualizada y la actualizó en el primer uso.

Además, no admitimos degradaciones, pero es por diseño, si algo se rompe en una actualización, restauramos la versión anterior y arreglamos la actualización antes de volver a intentarlo.

Fabio Gomes
fuente
4

Creo carpetas con el nombre de las versiones de compilación y pongo scripts de actualización y degradación allí. Por ejemplo, podría tener las siguientes carpetas: 1.0.0, 1.0.1 y 1.0.2. Cada uno contiene el script que le permite actualizar o degradar su base de datos entre versiones.

En caso de que un cliente o un cliente lo llame con un problema con la versión 1.0.1 y esté utilizando 1.0.2, devolver la base de datos a su versión no será un problema.

En su base de datos, cree una tabla llamada "esquema" donde coloque la versión actual de la base de datos. Luego, escribir un programa que pueda actualizar o degradar su base de datos por usted es fácil.

Justo como dijo Joey, si estás en un mundo de Rails, usa Migraciones. :)

Louis Salin
fuente
3

Para mi proyecto PHP actual utilizamos la idea de migraciones de rieles y tenemos un directorio de migraciones en el que guardamos el título de los archivos "migration_XX.sql" donde XX es el número de la migración. Actualmente, estos archivos se crean a mano a medida que se realizan las actualizaciones, pero su creación podría modificarse fácilmente.

Luego tenemos un script llamado "Migration_watcher" que, como estamos en pre-alpha, actualmente se ejecuta en cada carga de página y verifica si hay un nuevo archivo migration_XX.sql donde XX es más grande que la versión de migración actual. Si es así, ejecuta todos los archivos migration_XX.sql hasta el mayor número en la base de datos y ¡listo! Los cambios de esquema son automatizados.

Si necesita la capacidad de revertir el sistema requeriría muchos ajustes, pero es simple y ha funcionado muy bien para nuestro equipo bastante pequeño hasta ahora.

Eric Scrivner
fuente
3

Recomendaría usar Ant (multiplataforma) para el lado de "secuencias de comandos" (ya que prácticamente puede hablar con cualquier base de datos a través de jdbc) y Subversion para el repositorio de origen. Ant le permitirá "hacer una copia de seguridad" de su base de datos en archivos locales, antes de realizar cambios. 1. copia de seguridad del esquema de db existente para archivar a través de Ant 2. control de versión en el repositorio de Subversion a través de Ant 3. enviar nuevas instrucciones sql a db a través de Ant

Cruz
fuente
3

Toad for MySQL tiene una función llamada comparación de esquemas que le permite sincronizar 2 bases de datos. Es la mejor herramienta que he usado hasta ahora.

Petah
fuente
3

Me gusta la forma en que Yii maneja las migraciones de bases de datos. Una migración es básicamente una implementación de script PHP CDbMigration. CDbMigrationdefine un upmétodo que contiene la lógica de migración. También es posible implementar un downmétodo para soportar la inversión de la migración. Alternativamente, safeUpo safeDownpuede usarse para asegurarse de que la migración se realice en el contexto de una transacción.

La herramienta de línea de comandos de Yii yiiccontiene soporte para crear y ejecutar migraciones. Las migraciones se pueden aplicar o revertir, una por una o en un lote. La creación de una migración da como resultado un código para la implementación de una clase PHP CDbMigration, cuyo nombre exclusivo se basa en una marca de tiempo y un nombre de migración especificado por el usuario. Todas las migraciones que se han aplicado previamente a la base de datos se almacenan en una tabla de migración.

Para obtener más información, consulte el artículo sobre la migración de la base de datos del manual.

Ton van den Heuvel
fuente
2

Las migraciones de la OMI tienen un gran problema

Actualizar de una versión a otra funciona bien, pero realizar una nueva instalación de una versión determinada puede llevar una eternidad si tiene cientos de tablas y un largo historial de cambios (como nosotros).

Ejecutar todo el historial de deltas desde la línea de base hasta la versión actual (para cientos de bases de datos de clientes) puede llevar mucho tiempo.

Edson Medina
fuente
0

Existe una herramienta mysql-diff de línea de comandos que compara los esquemas de la base de datos, donde el esquema puede ser una base de datos en vivo o un script SQL en el disco. Es bueno para la mayoría de las tareas de migración de esquemas.

stepancheg
fuente