La solución que uso (originalmente desarrollada por un amigo) es otra adición a yukondude.
- 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.
- Crea una tabla de base de datos llamada "db_schema" con una columna entera llamada versión.
- 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.
¿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? –
@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