2008-08-29 8 views
14

Quizás el mayor riesgo para impulsar nuevas funcionalidades para la vida reside en las modificaciones de la base de datos requeridas por el nuevo código. En Rails, creo que tienen 'migraciones', en las que puede realizar cambios programáticos en su host de desarrollo y luego hacer los mismos cambios en vivo junto con el código que usa el esquema revisado. Y tira los dos hacia atrás si es necesario, de forma sincronizada.Migración de los cambios de la base de datos del desarrollo a vivo

¿Alguien ha encontrado un conjunto de herramientas similar para PHP/MySQL? Me encantaría escuchar al respecto, o cualquier solución programática o de proceso para ayudar a que esto sea menos riesgoso ...

Respuesta

2

Symfony tiene un complemento llamado sfMigrationsLight que maneja las migraciones básicas. CakePHP también tiene migraciones.

Por alguna razón, el soporte de migración nunca ha sido realmente una alta prioridad para la mayoría de los marcos de PHP y ORM que hay.

5

Nunca me he encontrado con una herramienta que haría el trabajo. En su lugar, he utilizado archivos individuales, numerados para que sepa qué orden ejecutar: básicamente, una versión manual de las migraciones de Rails, pero sin la reversión.

Aquí es el tipo de cosas que estoy hablando:

000-clean.sql   # wipe out everything in the DB 
001-schema.sql  # create the initial DB objects 
002-fk.sql   # apply referential integrity (simple if kept separate) 
003-reference-pop.sql # populate reference data 
004-release-pop.sql # populate release data 
005-add-new-table.sql # modification 
006-rename-table.sql # another modification... 

En realidad nunca he encontrado con problemas para la realización, pero no es muy elegante. Depende de usted rastrear qué scripts necesitan ejecutarse para una actualización dada (un esquema de numeración más inteligente podría ayudar). También funciona bien con control de fuente.

El tratamiento de los valores de clave sustitutos (de columnas de autonumeración) puede ser complicado, ya que la base de datos de producción probablemente tendrá valores diferentes a los de la base de datos de desarrollo. Por lo tanto, intento nunca hacer referencia a un valor de clave sustituta literal en ninguno de mis scripts de modificación, si es posible.

5

No confío en las migraciones programáticas. Si se trata de un cambio simple, como agregar una columna NULLable, simplemente lo agregaré directamente al servidor en vivo. Si es más complejo o requiere cambios de datos, escribiré un par de archivos de migración de SQL y los probaré contra una base de datos de réplicas.

Al usar migraciones, siempre pruebe la migración de retrotracción. Es su botón de emergencia "oh mierda".

2

Yo uso SQLyog para copiar la estructura, y SIEMPRE, permítanme repetir SIEMPRE primero una copia de seguridad.

3

He usado esta herramienta anteriormente y funcionó perfectamente.

http://www.mysqldiff.org/

Se toma como una entrada o bien una conexión DB o un archivo SQL, y lo compara con la misma (ya sea otra conexión DB u otro archivo de SQL). Puede escupir el SQL para realizar los cambios o hacer los cambios por usted.

3

@ [yukondude]

estoy usando Perl mí mismo, y me he ido por el camino de las migraciones de estilo carriles semi-manual de la misma manera.

Lo que hice fue tener una sola tabla "versión" con una sola columna "versión", que contiene una sola fila de un número que es la versión actual del esquema.Luego fue (bastante) trivial escribir un script para leer ese número, buscar en un directorio determinado y aplicar todas las migraciones numeradas para ir desde allí hasta aquí (y luego actualizar el número).

En mi entorno de desarrollador/escenario, con frecuencia (a través de otro script) extraigo los datos de producción en la base de datos provisional y ejecuto el script de migración. Si haces esto antes de lanzar, estarás bastante seguro de que las migraciones funcionarán. Obviamente, prueba extensivamente en su entorno de ensayo.

Etiqueto el nuevo código y las migraciones requeridas bajo una etiqueta de control de versión. Para implementar en vivo o por etapas, simplemente actualice todo a esta etiqueta y ejecute el script de migración con bastante rapidez. (Es posible que desee haber arreglado un tiempo de inactividad corto si es realmente cambios de esquema extravagantes.)

1

Más o menos lo que Lot105 describió.

Cada migración necesita una secuencia de comandos de aplicación y retrotracción, y usted tiene algún tipo de secuencia de comandos de control que verifica qué migración (es) deben aplicarse y las aplica en el orden apropiado.

Cada desarrollador entonces mantiene su base de datos sincronizada utilizando este esquema, y ​​cuando se aplica a la producción se aplican los cambios pertinentes. Los scripts de retrotracción se pueden mantener para revertir un cambio si es necesario.

Algunos cambios no se pueden hacer con un simple script ALTER, como una herramienta como sqldiff produciría; algunos cambios no requieren un cambio de esquema, sino un cambio programático de los datos existentes. Por lo tanto, no se puede generalizar, por lo que se necesita una secuencia de comandos editada por humanos.

0

Siempre he preferido mantener mi sitio de desarrollo apuntando a la misma base de datos que el sitio en vivo. Esto puede sonar arriesgado al principio, pero en realidad resuelve muchos problemas. Si tiene dos sitios en el mismo servidor que apuntan a la misma base de datos, obtendrá una vista en tiempo real y precisa de lo que verán los usuarios cuando entre en funcionamiento.

Solo tendrá 1 base de datos y siempre que establezca una política para nunca eliminar una columna de una tabla, sabrá que su nuevo código coincidirá con la base de datos que está utilizando.

También hay mucho menos estragos al migrar. Solo necesita moverse sobre los scripts de PHP y ya están probados usando el mismo DB.

También tiendo a crear un enlace simbólico a cualquier carpeta que sea un objetivo para cargas de usuarios. Esto significa que no hay confusión sobre qué archivos de usuario se han actualizado.

Otro efecto secundario es la opción de transferir un pequeño grupo de 'beta-testers' para usar el sitio en el uso diario. Esto puede llevar a una gran cantidad de comentarios que puede implementar antes de el lanzamiento público.

Esto puede no funcionar en todos los casos pero he comenzado a mover todas mis actualizaciones a este modelo. Ha causado un desarrollo y lanzamientos mucho más suaves.

+0

¿Cómo se maneja el cambio de nombre de las columnas? Un cambio de nombre rápido rompería su entorno de producción, ¿verdad? –

+0

@Kevin Pang: es cierto, pero no cambio el nombre de mis columnas con demasiada frecuencia. He descubierto que el demonio menor es dejar los nombres de las columnas como están. Me hace pensar cuidadosamente sobre los nombres de las columnas, pero también creo que es algo raro. Si debe cambiar el nombre, un reemplazo de búsqueda en dos sistemas no lleva mucho más tiempo que un sistema. Todavía causa menos tiempo de inactividad y agravamiento que una migración DB. Sé que no es convencional, pero me funciona muy bien :) – Paulo

2

La solución que uso (originalmente desarrollada por un amigo) es otra adición a yukondude.

  1. Crear un directorio de esquema bajo control de versiones y después de cada cambio que haga dB mantener un archivo .sql con el SQL que desea ejecutar junto con la consulta SQL para actualizar la tabla DB_SCHEMA.
  2. Crea una tabla de base de datos llamada "db_schema" con una columna entera llamada versión.
  3. En el directorio de esquema, cree dos scripts de shell, "actual" y "actualizar".La ejecución actual le dice a qué versión del esquema db está actualmente la base de datos a la que está conectado. La ejecución de la actualización ejecuta cada archivo .sql numerado de forma mayor a la versión en la tabla db_schema hasta que alcanza el archivo numerado más grande en su directorio de esquema.

archivos en el directorio de esquema:

0-init.sql 
1-add-name-to-user.sql 
2-add-bio.sql 

Lo que un archivo típico se parece, tenga en cuenta la actualización DB_SCHEMA al final de cada archivo .sql:

BEGIN; 
-- comment about what this is doing 
ALTER TABLE user ADD COLUMN bio text NULL; 

UPDATE db_schema SET version = 2; 
COMMIT; 

La secuencia de comandos "actual" (para psql):

#!/bin/sh 

VERSION=`psql -q -t <<EOF 
\set ON_ERROR_STOP on 
SELECT version FROM db_schema; 
EOF 
` 

[ $? -eq 0 ] && { 
    echo $VERSION 
    exit 0 
} 

echo 0 

la secuencia de actualización (también psql):

#!/bin/sh 

CURRENT=`./current` 
LATEST=`ls -vr *.sql |egrep -o "^[0-9]+" |head -n1` 

echo current is $CURRENT 
echo latest is $LATEST 

[[ $CURRENT -gt $LATEST ]] && { 
    echo That seems to be a problem. 
    exit 1 
} 

[[ $CURRENT -eq $LATEST ]] && exit 0 

#SCRIPT_SET="-q" 
SCRIPT_SET="" 

for ((I = $CURRENT + 1 ; I <= $LATEST ; I++)); do 
    SCRIPT=`ls $I-*.sql |head -n1` 
    echo "Adding '$SCRIPT'" 
    SCRIPT_SET="$SCRIPT_SET $SCRIPT" 
done 

echo "Applying updates..." 
echo $SCRIPT_SET 
for S in $SCRIPT_SET ; do 
    psql -v ON_ERROR_STOP=TRUE -f $S || { 
    echo FAIL 
    exit 1 
    } 
done 
echo OK 

Mi-0 init.sql tiene la estructura del esquema inicial completo, junto con la inicial "versión de actualización DB_SCHEMA SET = 0;". No debería ser demasiado difícil modificar estos scripts para MySQL. En mi caso también tengo

export PGDATABASE="dbname" 
export PGUSER="mike" 

en mi .bashrc. Y solicita una contraseña con cada archivo que se está ejecutando.

0

En el pasado he usado LiquiBase, una herramienta basada en Java donde configura sus migraciones como archivos XML. Puede generar el SQL necesario con él.

Hoy utilizaría la biblioteca Doctrine 2 que tiene migration facilities similar a Ruby.

El marco Symfony 2 también tiene una buena manera de lidiar con los cambios de esquema: su herramienta de línea de comandos puede analizar el esquema existente y generar SQL para hacer coincidir la base de datos con las definiciones de esquema modificadas.

+0

Interesante, gracias ... – Polsonby

Cuestiones relacionadas