¿Cómo debería construir su base de datos a partir del control de código fuente?


103

Ha habido alguna discusión en la wiki de la comunidad SO sobre si los objetos de la base de datos deben ser controlados por versiones. Sin embargo, no he visto mucha discusión sobre las mejores prácticas para crear un proceso de automatización de compilación para objetos de base de datos.

Este ha sido un punto polémico de discusión para mi equipo, particularmente porque los desarrolladores y DBA a menudo tienen diferentes objetivos, enfoques y preocupaciones al evaluar los beneficios y riesgos de un enfoque de automatización para la implementación de bases de datos.

Me gustaría escuchar algunas ideas de la comunidad SO sobre qué prácticas han sido efectivas en el mundo real.

Me doy cuenta de que es algo subjetivo qué prácticas son realmente las mejores, pero creo que un buen diálogo sobre qué trabajo podría ser útil para muchas personas.

Estas son algunas de mis preguntas teaser sobre áreas de interés en este tema. No se pretende que sean una lista definitiva, sino un punto de partida para que las personas me ayuden a comprender lo que estoy buscando.

  1. ¿Deben construirse tanto los entornos de prueba como los de producción a partir del control de código fuente?
    • ¿Deben construirse ambos utilizando la automatización, o la producción debe construirse copiando objetos de un entorno de prueba finalizado y estable?
    • ¿Cómo maneja las posibles diferencias entre los entornos de prueba y producción en los scripts de implementación?
    • ¿Cómo se prueba que los scripts de implementación funcionarán con la misma eficacia en la producción que en la prueba?
  2. ¿Qué tipos de objetos deben controlarse por versión?
    • ¿Solo código (procedimientos, paquetes, activadores, java, etc.)?
    • Índices?
    • Restricciones?
    • Definiciones de tablas
    • ¿Scripts de cambio de tabla? (por ejemplo, secuencias de comandos ALTER)
    • ¿Todo?
  3. ¿Qué tipos de objetos no deberían controlarse por versión?
    • Secuencias
    • ¿Subsidios?
    • ¿Cuentas de usuario?
  4. ¿Cómo deberían organizarse los objetos de la base de datos en su repositorio de SCM?
    • ¿Cómo maneja cosas únicas como scripts de conversión o scripts ALTER?
    • ¿Cómo maneja la retirada de objetos de la base de datos?
    • ¿Quién debería ser responsable de promover los objetos desde el desarrollo hasta el nivel de prueba?
    • ¿Cómo coordinas los cambios de varios desarrolladores?
    • ¿Cómo maneja la ramificación de los objetos de base de datos utilizados por múltiples sistemas?
  5. ¿Qué excepciones, si las hay, pueden hacerse razonablemente a este proceso?
    • ¿Temas de seguridad?
    • ¿Datos con problemas de desidentificación?
    • ¿Secuencias de comandos que no se pueden automatizar por completo?
  6. ¿Cómo puede hacer que el proceso sea resistente y ejecutable?
    • ¿Al error del desarrollador?
    • ¿A problemas medioambientales inesperados?
    • ¿Para recuperación ante desastres?
  7. ¿Cómo convence a los responsables de la toma de decisiones de que los beneficios de DB-SCM realmente justifican el costo?
    • ¿Evidencia anecdótica?
    • ¿Investigación de la industria?
    • ¿Recomendaciones de mejores prácticas de la industria?
    • ¿Apelaciones a autoridades reconocidas?
    • ¿Análisis coste-beneficio?
  8. ¿Quién debería "poseer" los objetos de la base de datos en este modelo?
    • Desarrolladores?
    • DBA?
    • Analistas de datos?
    • ¿Más de uno?

3
La profundidad de esta pregunta pide una recompensa.
Greg D

Respuestas:


53

Aquí hay algunas respuestas a sus preguntas:

  1. ¿Deben construirse los entornos de prueba y de producción a partir del control de código fuente? SI
    • ¿Deben construirse ambos utilizando la automatización, o la producción debe construirse copiando objetos de un entorno de prueba finalizado y estable?
    • Automatización para ambos. NO copie datos entre los entornos
    • ¿Cómo maneja las posibles diferencias entre los entornos de prueba y producción en los scripts de implementación?
    • Use plantillas, de modo que realmente pueda producir diferentes conjuntos de scripts para cada entorno (por ejemplo, referencias a sistemas externos, bases de datos vinculadas, etc.)
    • ¿Cómo se prueba que los scripts de implementación funcionarán con la misma eficacia en la producción que en la prueba?
    • Los prueba en un entorno de preproducción: pruebe la implementación en una copia exacta del entorno de producción (base de datos y potencialmente otros sistemas)
  2. ¿Qué tipos de objetos deben controlarse por versión?
    • ¿Solo código (procedimientos, paquetes, activadores, java, etc.)?
    • Índices?
    • Restricciones?
    • Definiciones de tablas
    • ¿Scripts de cambio de tabla? (por ejemplo, secuencias de comandos ALTER)
    • ¿Todo?
    • Todo y:
      • No olvide los datos estáticos (listas de búsqueda, etc.), por lo que no necesita copiar NINGÚN dato entre entornos
      • Mantenga solo la versión actual de los scripts de la base de datos (versión controlada, por supuesto), y
      • Almacene los scripts ALTER: 1 script GRANDE (o directorio de scripts llamado me gusta 001_AlterXXX.sql, de modo que ejecutarlos en orden de clasificación natural se actualizará de la versión A a B)
  3. ¿Qué tipos de objetos no deberían controlarse por versión?
    • Secuencias
    • ¿Subsidios?
    • ¿Cuentas de usuario?
    • ver 2. Si sus usuarios / roles (o nombres de usuarios técnicos) son diferentes entre los entornos, aún puede escribirlos usando plantillas (ver 1.)
  4. ¿Cómo deberían organizarse los objetos de la base de datos en su repositorio de SCM?
    • ¿Cómo maneja cosas únicas como scripts de conversión o scripts ALTER?
    • ver 2.
    • ¿Cómo maneja la retirada de objetos de la base de datos?
    • eliminado de la base de datos, eliminado del tronco / sugerencia de control de fuente
    • ¿Quién debería ser responsable de promover los objetos desde el desarrollo hasta el nivel de prueba?
    • programa de desarrollo / prueba / lanzamiento
    • ¿Cómo coordinas los cambios de varios desarrolladores?
    • NO intente crear una base de datos separada para cada desarrollador. usas el control de fuente, ¿verdad? en este caso, los desarrolladores cambian la base de datos y registran los scripts. para estar completamente seguro, vuelva a crear la base de datos a partir de los scripts durante la compilación nocturna
    • ¿Cómo maneja la ramificación de los objetos de base de datos utilizados por múltiples sistemas?
    • uno difícil: trata de evitarlo a toda costa.
  5. ¿Qué excepciones, si las hay, pueden hacerse razonablemente a este proceso?
    • ¿Temas de seguridad?
    • no almacene contraseñas para prueba / prod. puede permitirlo para el desarrollo, especialmente si ha automatizado reconstrucciones de bases de datos diarias / nocturnas
    • ¿Datos con problemas de desidentificación?
    • ¿Secuencias de comandos que no se pueden automatizar por completo?
    • documentar y almacenar con el script de información de lanzamiento / ALTER
  6. ¿Cómo puede hacer que el proceso sea resistente y ejecutable?
    • ¿Al error del desarrollador?
    • probado con la compilación diaria desde cero, y compare los resultados con la actualización incremental (de la versión A a la B usando ALTER). comparar tanto el esquema resultante como los datos estáticos
    • ¿A problemas medioambientales inesperados?
    • utilizar el control de versiones y las copias de seguridad
    • compare el esquema de la base de datos PROD con lo que cree que es, especialmente antes de la implementación. SuperDuperCool DBA puede haber corregido un error que nunca estuvo en su sistema de tickets :)
    • ¿Para recuperación ante desastres?
  7. ¿Cómo convence a los responsables de la toma de decisiones de que los beneficios de DB-SCM realmente justifican el costo?
    • ¿Evidencia anecdótica?
    • ¿Investigación de la industria?
    • ¿Recomendaciones de mejores prácticas de la industria?
    • ¿Apelaciones a autoridades reconocidas?
    • ¿Análisis coste-beneficio?
    • Si los desarrolladores y los administradores de bases de datos están de acuerdo, no es necesario que convenza a nadie, creo (a menos que necesite dinero para comprar un software como dbGhost para MSSQL)
  8. ¿Quién debería "poseer" los objetos de la base de datos en este modelo?
    • Desarrolladores?
    • DBA?
    • Analistas de datos?
    • ¿Más de uno?
    • Por lo general, los administradores de bases de datos aprueban el modelo (antes del registro o después como parte de la revisión del código). Definitivamente poseen objetos relacionados con el rendimiento. Pero, en general, el equipo lo posee [y el empleador, por supuesto :)]

¡Gracias por tu respuesta! ¿Cree que estas recomendaciones se aplican a todos los proyectos? ¿Conoce alguna herramienta que ayude a alcanzar este nivel de automatización? Actualizaré mi pregunta a medida que más personas la evalúen. Además, tenga en cuenta que mis preguntas "teaser" no pretendían ser una lista definitiva de preocupaciones a abordar, sino más bien un punto de partida para la discusión.
LBushkin

Claro. Creo que planteaste una muy, muy buena pregunta. Y realmente espero que la pregunta tenga suficiente tracción para que compile un excelente wiki de HowTo sobre el tema. ---- de las herramientas: utilicé dbGhost de Innovartis, que mencioné en las respuestas para administrar el servidor MSSQL e hizo un gran trabajo. Probablemente haya otras herramientas para el trabajo, pero dado que el esquema SQL completo no es realmente estándar entre los proveedores, no existe una solución todo en uno (para todos los SCM y RDMBS).
furgoneta

Buena respuesta. Supongo que "buscar listas" se refiere a los datos que se utilizan para rellenar cuadros <select>. Es posible que eso no siempre sea posible, ya que los usuarios (de alguna manera) pueden modificar los datos en producción. Mantener copias de seguridad tiene sentido en este caso. También sugiere recrear la base de datos desde cero como parte de una compilación nocturna. No creo que sea una buena idea; puede eliminar el trabajo en curso o requerir la reinstalación / configuración de otro software. Finalmente, sugeriría crear modos de prueba, validadores de datos y otras herramientas en lugar de construir desde cero para garantizar procesos resilientes.
Richard Levasseur

@Ricardo. Buenos puntos, pero aún así. Cuando lee "construya una base de datos desde cero", no siempre significa eliminar los datos. Es reconstruir el esquema y los datos estáticos. Si hay algún trabajo en progreso (con respecto al esquema o los datos estáticos), debería estar en el control de fuente, por lo que será parte de la compilación nocturna. Si trabaja en la rama con un rediseño importante de la base de datos, tiene una base de datos separada para este tipo de desarrollo. Y si usa pruebas unitarias, entonces no confía en el estado de los datos en la base de datos, sino que crea / elimina como parte de db-unit-test. --- Datos estáticos prescindibles por los usuarios - de acuerdo.
furgoneta

No estoy de acuerdo con la reconstrucción de bases de datos todas las noches. Si bien todo para definir la base de datos, como esquemas, desencadenadores, procedimientos almacenados y ciertos datos estáticos "administrados" debe estar programado, el material real no debe serlo. El contenido en sí puede ser impulsado por tareas del desarrollador. Tenemos desarrolladores que trabajan en conjuntos de datos para probar y experimentar. ¿Qué pasa si vienen todos los días y su estado actual se "restablece"? No está bien. Utilizo pruebas TestNG que borran ciertas tablas y luego se cargan previamente con datos de prueba todos los días. No suena como un candidato para el control de fuente.
gregturn

5

Trato el SQL como código fuente cuando es posible

Si puedo escribirlo en SQL compatible con el estándar, generalmente va en un archivo en mi control de código fuente. El archivo definirá tanto como sea posible, como SP, declaraciones CREATE de tabla.

También incluyo datos ficticios para probar en control de fuente:

  1. proj / sql / setup_db.sql
  2. proj / sql / dummy_data.sql
  3. proj / sql / mssql_specific.sql
  4. proj / sql / mysql_specific.sql

Y luego abstraigo todas mis consultas SQL para poder construir el proyecto completo para MySQL, Oracle, MSSQL o cualquier otra cosa.

La automatización de compilación y prueba utiliza estos scripts de compilación, ya que son tan importantes como la fuente de la aplicación y prueba todo, desde la integridad hasta los desencadenantes, los procedimientos y el registro.


4

Utilizamos la integración continua a través de TeamCity. En cada registro en el control de fuente, la base de datos y todos los datos de prueba se reconstruyen desde cero, luego el código, luego las pruebas unitarias se ejecutan contra el código. Si está utilizando una herramienta de generación de código como CodeSmith, también se puede colocar en su proceso de compilación para generar su capa de acceso a los datos con cada compilación, asegurándose de que todas sus capas "coincidan" y no produzcan errores debido a parámetros de SP no coincidentes o columnas faltantes.

Cada compilación tiene su propia colección de scripts SQL que se almacenan en el directorio $ project \ SQL \ en el control de código fuente, se les asigna un prefijo numérico y se ejecutan en orden. De esa manera, practicamos nuestro procedimiento de implementación en cada compilación.

Dependiendo de la tabla de búsqueda, la mayoría de nuestros valores de búsqueda también se almacenan en scripts y se ejecutan para asegurarse de que los datos de configuración sean los que esperamos para, digamos, "código_razón" o "código_país". De esta forma podemos realizar un cambio de búsqueda de datos en el desarrollo, probarlo y luego "promoverlo" a través del control de calidad y la producción, en lugar de utilizar una herramienta para modificar los valores de búsqueda en producción, lo que puede ser peligroso para el tiempo de actividad.

También creamos un conjunto de scripts de "reversión" que deshacen los cambios de nuestra base de datos, en caso de que una compilación para producción salga mal. Puede probar los scripts de reversión ejecutándolos y luego volver a ejecutar las pruebas unitarias para la versión de compilación una debajo de la suya, después de que se ejecuten sus scripts de implementación.


4

+1 para Liquibase : LiquiBase es una biblioteca de código abierto (LGPL), independiente de la base de datos para rastrear, administrar y aplicar cambios en la base de datos. Se basa en una premisa simple: todos los cambios de la base de datos (estructura y datos) se almacenan de una manera descriptiva basada en XML y se registran en el control de fuente. El buen punto es que los cambios de DML se almacenan semánticamente, no solo diff, para que pueda rastrear el propósito de los cambios.

Se podría combinar con el control de versiones GIT para una mejor interacción. Voy a configurar nuestro entorno dev-prod para probarlo.

También puede usar Maven, los sistemas de compilación Ant para compilar código de producción a partir de scripts.

El inconveniente es que LiquiBase no se integra en los IDE de SQL generalizados y debe realizar las operaciones básicas usted mismo.

Además de esto, puede usar DBUnit para pruebas de bases de datos: esta herramienta permite que los scripts de generación de datos se utilicen para probar su entorno de producción con limpieza posterior.

EN MI HUMILDE OPINIÓN:

  1. Almacene DML en archivos para poder versionarlos.
  2. Automatice el proceso de creación de esquemas desde el control de la fuente.
  3. Con fines de prueba, el desarrollador puede usar la base de datos local creada a partir del control de código fuente a través del sistema de compilación + datos de prueba de carga con scripts o scripts DBUnit (desde Source Control).
  4. LiquiBase le permite proporcionar una "secuencia de ejecución" de scripts para respetar las dependencias.
  5. Debe haber un equipo de DBA que verifique el brunch maestro con TODOS los cambios antes del uso de producción. Quiero decir que verifican el tronco / rama de otros DBA antes de comprometerse con el tronco MASTER. Para que el maestro sea siempre consistente y esté listo para la producción.

Enfrentamos todos los problemas mencionados con cambios de código, fusión y reescritura en nuestra base de datos de producción de facturación. Este tema es genial para descubrir todas esas cosas.


3

Al hacer "preguntas teaser", parece estar más interesado en una discusión que en la opinión de alguien sobre las respuestas finales. La lista de correo activa (> 2500 miembros) agileDatabases ha abordado muchas de estas preguntas y es, en mi experiencia, un foro sofisticado y civil para este tipo de discusión.


Creo que es poco probable que se pueda alcanzar una respuesta única y universalmente acordada. Pero me gustaría identificar algunas áreas comunes de acuerdo, y tal vez armar una recomendación razonable. Definitivamente también miraré el foro de bases de datos ágiles, gracias.
LBushkin

3

Básicamente estoy de acuerdo con todas las respuestas dadas por van . Para obtener más información, mi línea de base para la gestión de bases de datos es la serie de K. Scott Allen (una lectura obligada, en mi humilde opinión. Y la opinión de Jeff también parece).

  • Objetos de bases de datos siempre pueden ser reconstruidos a partir de cero con el lanzamiento de un archivo SQL individual (que en sí puede llamar a otros archivos SQL): Create.sql. Esto puede incluir la inserción de datos estáticos (listas ...).
  • Los scripts SQL están parametrizados de modo que no se almacene información sensible o dependiente del entorno en archivos sin formato.
  • Yo uso un archivo por lotes personalizado para el lanzamiento Create.sql: Create.cmd. Su objetivo es principalmente verificar los requisitos previos (herramientas, variables de entorno ...) y enviar parámetros al script SQL. También puede cargar datos estáticos de archivos CSV de forma masiva por problemas de rendimiento.
  • Normalmente, las credenciales de usuario del sistema se pasarían como un parámetro al Create.cmdarchivo.

En mi humilde opinión, la carga dinámica de datos debería requerir otro paso, dependiendo de su entorno. Los desarrolladores querrán cargar su base de datos con prueba, basura o ningún dato, mientras que en el otro extremo los gerentes de producción querrán cargar datos de producción. También consideraría almacenar datos de prueba en el control de fuente (para facilitar las pruebas unitarias, por ejemplo).

Una vez que la primera versión de la base de datos se haya puesto en producción, no solo necesitará crear scripts (principalmente para desarrolladores), sino también actualizar los scripts (basados ​​en los mismos principios):

  • Debe haber una forma de recuperar la versión de la base de datos (yo uso un procedimiento almacenado, pero una tabla también funcionaría).
  • Antes de lanzar una nueva versión, creo un Upgrade.sqlarchivo (que puede llamar a otros) que permite actualizar la versión N-1 a la versión N (siendo N la versión que se lanza). Guardo este script en una carpeta llamada N-1.
  • Tengo un archivo por lotes que hace la actualización: Upgrade.cmd. Puede recuperar la versión actual (CV) de la base de datos a través de una simple instrucción SELECT, iniciar el Upgrade.sqlscript almacenado en la CVcarpeta y repetir hasta que no se encuentre ninguna carpeta. De esta manera, puede actualizar automáticamente de, digamos, N-3 a N.

Los problemas con esto son:

  • Es difícil comparar automáticamente los esquemas de bases de datos, dependiendo de los proveedores de bases de datos. Esto puede generar secuencias de comandos de actualización incompletas.
  • Cada cambio en el entorno de producción (normalmente realizado por los administradores de bases de datos para el ajuste del rendimiento) también debería llegar al control de fuente. Para asegurarse de esto, generalmente es posible registrar cada modificación en la base de datos a través de un disparador. Este registro se restablece después de cada actualización.
  • Sin embargo, lo ideal es que los cambios iniciados por el DBA sean parte del proceso de lanzamiento / actualización cuando sea posible.

¿En cuanto a qué tipo de objetos de la base de datos desea tener bajo control de código fuente? Bueno, diría tanto como sea posible, pero no más ;-) Si desea crear usuarios con contraseñas, consígales una contraseña predeterminada (inicio de sesión / inicio de sesión, práctica para propósitos de prueba de unidades) y haga que el cambio de contraseña sea una operación manual . Esto sucede mucho con Oracle donde los esquemas también son usuarios ...


1

Tenemos nuestro proyecto Silverlight con base de datos MSSQL en control de versiones Git. La forma más sencilla es asegurarse de tener una base de datos reducida (en cuanto al contenido) y hacer un volcado completo de fe Visual Studio. Luego puede hacer 'sqlcmd' desde su script de compilación para recrear la base de datos en cada máquina de desarrollo.

Para la implementación, esto no es posible porque las bases de datos son demasiado grandes: esa es la razón principal para tenerlas en una base de datos en primer lugar.


1

Creo firmemente que una base de datos debería ser parte del control de código fuente y, en gran medida, parte del proceso de construcción. Si está en control de fuente, tengo las mismas protecciones de codificación cuando escribo un procedimiento almacenado en SQL que cuando escribo una clase en C #. Hago esto al incluir un directorio de scripts de base de datos debajo de mi árbol de fuentes. Este directorio de scripts no tiene necesariamente un archivo para un objeto en la base de datos. ¡Eso sería un dolor en el trasero! Desarrollo en mi base de datos solo lo haría en mi proyecto de código. Luego, cuando estoy listo para registrarme, hago una diferencia entre la última versión de mi base de datos y la actual en la que estoy trabajando. Utilizo SQL Compare para esto y genera un script de todos los cambios. Luego, este script se guarda en mi directorio db_update con una convención de nomenclatura específica 1234_TasksCompletedInThisIteration donde el número es el siguiente número en el conjunto de scripts que ya están allí, y el nombre describe lo que se está haciendo en este registro. Hago esto de esta manera porque como parte de mi proceso de compilación, comienzo con una base de datos nueva que luego se construye programáticamente usando los scripts en este directorio. Escribí una tarea NAnt personalizada que itera a través de cada script ejecutando su contenido en la base de datos. Obviamente, si necesito algunos datos para ingresar a la base de datos, también tengo scripts de inserción de datos. Esto también tiene muchos beneficios. Uno, todas mis cosas están versionadas. Dos, cada compilación es una compilación nueva, lo que significa que no habrá cosas furtivas que se abran paso en mi proceso de desarrollo (como datos sucios que causan rarezas en el sistema). Tres, cuando se agrega un nuevo chico al equipo de desarrollo, simplemente necesitan obtener lo último y su desarrollador local está construido para ellos sobre la marcha. Cuatro, puedo ejecutar casos de prueba (¡no lo llamé "prueba unitaria"!) En mi base de datos, ya que el estado de la base de datos se restablece con cada compilación (lo que significa que puedo probar mis repositorios sin preocuparme por agregar datos de prueba al db).

Esto no es para todos.

Esto no es para todos los proyectos. ¡Normalmente trabajo en proyectos de campo verde, lo que me permite esta comodidad!


Me alegra saber que está utilizando SQL Compare como parte del ciclo de vida de desarrollo de su base de datos. Creemos que hemos mejorado la facilidad para que los desarrolladores obtengan nuevos cambios. Consulte Control de código fuente SQL. Esto funciona junto con SQL Compare para facilitar la colaboración del desarrollador, así como para permitirle mantener el origen de sus objetos de esquema controlado (siempre que esté usando SVN o TFS). red-gate.com/products/sql_source_control/index.htm
David Atkinson

1

En lugar de entrar en argumentos de torre blanca, aquí hay una solución que me ha funcionado muy bien en problemas del mundo real.

La creación de una base de datos desde cero se puede resumir en la gestión de scripts SQL.

DBdeploy es una herramienta que comprobará el estado actual de una base de datos, por ejemplo, qué scripts se han ejecutado previamente en ella, qué scripts están disponibles para ejecutar y, por lo tanto, qué scripts se necesitan para ejecutar.

Luego, recopilará todos los scripts necesarios y los ejecutará. Luego registra qué scripts se han ejecutado.

No es la herramienta más bonita ni la más compleja, pero con una gestión cuidadosa puede funcionar muy bien. Es de código abierto y fácilmente extensible. Una vez que la ejecución de los scripts se maneja bien, se pueden agregar fácilmente algunos componentes adicionales, como un script de shell que verifica los últimos scripts y ejecuta dbdeploy contra una instancia en particular.

Vea una buena introducción aquí:

http://code.google.com/p/dbdeploy/wiki/GettingStarted



Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.