Me costó mucho tratar de encontrar buenos ejemplos de cómo administrar esquemas de bases de datos y datos entre servidores de desarrollo, prueba y producción.
Aquí está nuestra configuración. Cada desarrollador tiene una máquina virtual que ejecuta nuestra aplicación y la base de datos MySQL. Es su sandbox personal para hacer lo que quieran. Actualmente, los desarrolladores realizarán un cambio en el esquema SQL y realizarán un volcado de la base de datos en un archivo de texto que comprometerán en SVN.
Queremos implementar un servidor de desarrollo de integración continua que siempre ejecutará el último código comprometido. Si lo hacemos ahora, volverá a cargar la base de datos desde SVN para cada compilación.
Tenemos un servidor de prueba (virtual) que ejecuta "candidatos de lanzamiento". La implementación en el servidor de prueba es actualmente un proceso muy manual, y generalmente implica que cargue el último SQL de SVN y lo modifique. Además, los datos en el servidor de prueba son inconsistentes. Terminas con los datos de prueba que el último desarrollador que confirmó tenía en su servidor sandbox.
Donde todo se rompe es el despliegue a la producción. Como no podemos sobrescribir los datos en vivo con los datos de prueba, esto implica volver a crear manualmente todos los cambios de esquema. Si hubo una gran cantidad de cambios de esquema o scripts de conversión para manipular los datos, esto puede ser realmente complicado.
Si el problema fuera solo el esquema, sería un problema más fácil, pero hay datos "básicos" en la base de datos que también se actualizan durante el desarrollo, como metadatos en las tablas de seguridad y permisos.
Esta es la barrera más grande que veo para avanzar hacia la integración continua y la construcción en un solo paso. ¿Cómo se soluciona esto?
Una pregunta de seguimiento: ¿cómo realiza un seguimiento de las versiones de la base de datos para saber qué scripts ejecutar para actualizar una instancia de base de datos determinada? ¿Una tabla de versiones como Lance menciona debajo del procedimiento estándar?
Gracias por la referencia a Tarantino. No estoy en un entorno .NET, pero su página wiki de DataBaseChangeMangement me pareció muy útil. Especialmente esta presentación de PowerPoint (.ppt)
Voy a escribir un script de Python que verifica los nombres de los *.sql
scripts en un directorio dado contra una tabla en la base de datos y ejecuta los que no están allí en orden en función de un número entero que forma la primera parte del nombre de archivo. Si es una solución bastante simple, como sospecho que será, la publicaré aquí.
Tengo un script de trabajo para esto. Se encarga de inicializar la base de datos si no existe y ejecuta scripts de actualización según sea necesario. También hay conmutadores para borrar una base de datos existente e importar datos de prueba de un archivo. Son alrededor de 200 líneas, por lo que no lo publicaré (aunque podría ponerlo en pastebin si hay interés).
Respuestas:
Hay un par de buenas opciones. No usaría la estrategia "restaurar una copia de seguridad".
Escriba todos los cambios en su esquema y haga que su servidor CI ejecute esos scripts en la base de datos. Tenga una tabla de versiones para realizar un seguimiento de la versión actual de la base de datos y solo ejecute los scripts si son para una versión más nueva.
Utiliza una solución de migración. Estas soluciones varían según el idioma, pero para .NET utilizo Migrator.NET. Esto le permite versionar su base de datos y moverse hacia arriba y hacia abajo entre versiones. Su esquema se especifica en el código C #.
fuente
Sus desarrolladores necesitan escribir scripts de cambio (cambio de esquema y datos) para cada error / característica en la que trabajan, no simplemente volcar toda la base de datos en el control de origen. Estas secuencias de comandos actualizarán la base de datos de producción actual a la nueva versión en desarrollo.
Su proceso de compilación puede restaurar una copia de la base de datos de producción en un entorno apropiado y ejecutar todos los scripts del control de origen en él, lo que actualizará la base de datos a la versión actual. Hacemos esto a diario para asegurarnos de que todos los scripts se ejecuten correctamente.
fuente
Echa un vistazo a cómo Ruby on Rails hace esto.
Primero están los llamados archivos de migración, que básicamente transforman el esquema de la base de datos y los datos de la versión N a la versión N + 1 (o en caso de degradación de la versión N + 1 a N). La base de datos tiene una tabla que indica la versión actual.
Las bases de datos de prueba siempre se limpian antes de las pruebas unitarias y se rellenan con datos fijos de los archivos.
fuente
El libro Refactoring Databases: Evolutionary Database Design puede darle algunas ideas sobre cómo administrar la base de datos. También se puede leer una versión corta en http://martinfowler.com/articles/evodb.html
En un proyecto PHP + MySQL, tuve el número de revisión de la base de datos almacenado en la base de datos, y cuando el programa se conecta a la base de datos, primero verificará la revisión. Si el programa requiere una revisión diferente, abrirá una página para actualizar la base de datos. Cada actualización se especifica en el código PHP, que cambiará el esquema de la base de datos y migrará todos los datos existentes.
fuente
dev_<<db>> , tst_<<db>> , stg_<<db>> , prd_<<db>>
(Obviamente, nunca debe codificar los nombres de bases de datosfuente
Esto es algo con lo que estoy constantemente insatisfecho: nuestra solución a este problema es. Durante varios años mantuvimos un script de cambio separado para cada versión. Este script contendría los deltas de la última versión de producción. Con cada lanzamiento de la aplicación, el número de versión se incrementaría, dando algo como lo siguiente:
Esto funcionó bastante bien hasta que comenzamos a mantener dos líneas de desarrollo: Trunk / Mainline para nuevos desarrollos, y una rama de mantenimiento para corrección de errores, mejoras a corto plazo, etc. Inevitablemente, surgió la necesidad de realizar cambios en el esquema en la rama. En este punto, ya teníamos dbChanges_n + 1.sql en el tronco, por lo que terminamos con un esquema como el siguiente:
Nuevamente, esto funcionó bastante bien, hasta que un día miramos hacia arriba y vimos 42 scripts delta en la línea principal y 10 en la rama. ARGH!
En estos días simplemente mantenemos un script delta y dejamos que SVN lo versione, es decir, sobrescribimos el script con cada lanzamiento. Y evitamos hacer cambios de esquema en las ramas.
Por lo tanto, tampoco estoy satisfecho con esto. Me gusta mucho el concepto de migraciones de Rails. Me he fascinado bastante con LiquiBase . Admite el concepto de refactorizaciones incrementales de la base de datos. Vale la pena echarle un vistazo y lo veré en detalle pronto. ¿Alguien tiene experiencia con eso? Me daría mucha curiosidad saber de tus resultados.
fuente
También puede considerar el uso de una herramienta como SQL Compare to script, la diferencia entre varias versiones de una base de datos, lo que le permite migrar rápidamente entre versiones
fuente
Tenemos una configuración muy similar al OP.
Los desarrolladores se desarrollan en máquinas virtuales con bases de datos privadas.
[Los desarrolladores pronto se comprometerán en sucursales privadas]
Las pruebas se ejecutan en diferentes máquinas (en realidad en máquinas virtuales alojadas en un servidor) [Pronto será ejecutado por el servidor Hudson CI]
Pruebe cargando el volcado de referencia en la base de datos. Aplique los parches del esquema de los desarrolladores y luego aplique los parches de datos de los desarrolladores
Luego ejecute las pruebas unitarias y del sistema.
La producción se implementa a los clientes como instaladores.
Lo que hacemos:
Tomamos un volcado de esquema de nuestra base de datos sandbox. Luego un volcado de datos sql. Diferimos eso a la línea de base anterior. ese par de deltas es actualizar n-1 a n.
Configuramos los volcados y deltas.
Entonces, para instalar la versión N CLEAN, ejecutamos el volcado en una base de datos vacía. Para parchear, aplique los parches intermedios.
(Juha mencionó que la idea de Rail de tener una tabla que grabe la versión actual de DB es buena y debería hacer que la instalación de actualizaciones sea menos complicada).
Los deltas y los volcados deben revisarse antes de la prueba beta. No puedo ver nada al respecto, ya que he visto a los desarrolladores insertar cuentas de prueba en la base de datos por sí mismos.
fuente
Me temo que estoy de acuerdo con otros carteles. Los desarrolladores necesitan escribir sus cambios.
En muchos casos, una ALTER TABLE simple no funcionará, también debe modificar los datos existentes: los desarrolladores deben pensar qué migraciones son necesarias y asegurarse de que estén escritas correctamente (por supuesto, debe probar esto cuidadosamente en algún momento el ciclo de lanzamiento).
Además, si tiene algún sentido, también hará que sus desarrolladores hagan retrocesos de script para sus cambios para que puedan revertirse si es necesario. Esto también debe probarse, para garantizar que su reversión no solo se ejecute sin errores, sino que deje la base de datos en el mismo estado en que se encontraba anteriormente (esto no siempre es posible o deseable, pero es una buena regla la mayor parte del tiempo) .
Cómo lo conectas a un servidor CI, no lo sé. Tal vez su servidor CI necesita tener una instantánea de compilación conocida, a la que revierte cada noche y luego aplica todos los cambios desde entonces. Probablemente sea lo mejor, de lo contrario, un script de migración roto no solo romperá la compilación de esa noche, sino todos los posteriores.
fuente
Eche un vistazo a dbdeploy , ya hay herramientas Java y .net disponibles, puede seguir sus estándares para los diseños de archivos SQL y la tabla de versiones de esquema y escribir su versión de Python.
fuente
Estamos usando la línea de comandos mysql-diff : genera una diferencia entre dos esquemas de base de datos (de Live DB o script) como ALTER script. mysql-diff se ejecuta al inicio de la aplicación, y si el esquema cambia, informa al desarrollador. Por lo tanto, los desarrolladores no necesitan escribir ALTER manualmente, las actualizaciones de esquema se producen de forma semiautomática.
fuente
Si está en el entorno .NET, la solución es Tarantino (archivado) . Maneja todo esto (incluyendo qué scripts sql instalar) en una compilación NANT.
fuente
He escrito una herramienta que (al conectarse a Open DBDiff ) compara los esquemas de la base de datos y le sugerirá scripts de migración. Si realiza un cambio que elimina o modifica datos, arrojará un error, pero proporcionará una sugerencia para el script (por ejemplo, cuando falta una columna en el nuevo esquema, verificará si la columna ha cambiado de nombre y creará xx - generado script.sql.suggestion que contiene una declaración de cambio de nombre).
http://code.google.com/p/migrationscriptgenerator/ Solo SQL Server me temo :( También es bastante alfa, pero tiene MUY baja fricción (particularmente si lo combinas con Tarantino o http://code.google .com / p / simplescriptrunner / )
La forma en que lo uso es tener un proyecto de scripts SQL en su .sln. También tiene una base de datos db_next localmente a la que realiza sus cambios (usando Management Studio o NHibernate Schema Export o LinqToSql CreateDatabase o algo así). Luego ejecuta migrationscriptgenerator con las bases de datos _dev y _next, que crea. los scripts de actualización de SQL para migrar.
fuente
Para la base de datos oracle utilizamos las herramientas oracle-ddl2svn .
Esta herramienta automatizó el siguiente proceso
cambios entre instancias resueltos manualmente
fuente