Control de fuente de esquema MySQL

En mi empresa tenemos varios desarrolladores trabajando en proyectos internos, cada uno con su propia configuration de caja virtual. Usamos SVN para manejar el origen, pero ocasionalmente encontramos problemas en los que es necesario cambiar el esquema de la database (MySQL), y esto tiene que propagarse a todos los demás desarrolladores. Por el momento tenemos un file de logging escrito manualmente que enumera lo que ha cambiado y el SQL necesario para realizar el cambio.

Espero que haya una mejor solución, idealmente una vinculada a SVN, por ejemplo, si actualiza a la revisión 893, el sistema sabe que esto requiere la revisión de la database 183 y actualiza su esquema local de forma automática. No nos preocupan los datos que se sincronizan, solo el esquema.

Por supuesto, una solución sería hacer que todos los desarrolladores ejecutaran una única database central; sin embargo, esto tiene la desventaja de que un cambio de esquema podría romper la construcción de todos los demás hasta que hagan un svn up.

Una opción es un dictionary de datos en YAML / JSON. Hay un buen artículo aquí

Consideraría mirar algo así como las herramientas de migration de esquemas de MyBatis . No es exactamente lo que describes, pero creo que resuelve tu problema de una manera elegante y puede usarse sin tener que introducir el núcleo MyBatis.

En términos de rodar el suyo, lo que siempre he hecho es tener un file de esquema base que creará el esquema desde cero, así como un file delta que agrega todos los cambios de esquema como deltas, separados por numbers de versión (puede probar y use numbers SVN, pero siempre me resulta más fácil simplemente incrementar manualmente). Luego, tenga una tabla schema_version, que contenga esa información para la database en vivo, el file de esquema canónico tendrá esa información y tendrá un script que ejecutará todos los cambios posteriores a la versión de DB existente del script delta.

Entonces tendrías un esquema como:

-- Version: 1 CREATE TABLE user ( id bigint, name varchar(20)) 

Tiene la herramienta para administrar la tabla de versiones del esquema y ver algo como:

 > SELECT * FROM schema_version; 1,2011-05-05 

Luego, algunas personas agregan al esquema y tienen un file delta que se vería así:

 -- Version: 2 ALTER TABLE user ADD email varchar(20); -- Version: 3 ALTER TABLE user ADD phone varchar(20); 

Y un nuevo esquema correspondiente se registró con:

 -- Version: 3 CREATE TABLE user ( id bigint, name varchar(20), email charchar(20), phone varchar(20)) 

Cuando ejecuta el script delta en una database con el esquema inicial (Versión 1), leerá el valor de la tabla schema_version y aplicará todos los deltas superiores a su esquema. Esto se torna más complicado cuando comienzas a tratar con twigs, pero sirve como un simple punto de partida.

Hay un par de enfoques que he usado antes o que uso actualmente:

Número de versión secuencial

La mayoría de los que usan este enfoque tienen un progtwig separado que toma un número de versión de la database y luego ejecuta cualquier statement asociada con versiones de bases de datos superiores a ese número, y finalmente actualiza el número de versión en la database.

Por lo tanto, si la versión es 37 y hay declaraciones asociadas con la versión 1 a la 38 en la aplicación de actualización, omitirá del 1 al 37 y ejecutará las declaraciones para llevar la database a la versión 38.

He visto implementaciones que también permiten declaraciones de degradación para cada versión para deshacer lo que hizo la actualización, y esto permite llevar una database desde la versión 38 a la versión 37.

En mi situación, teníamos esta actualización de la database en la aplicación en sí y no tenía degradaciones. Por lo tanto, los cambios fueron controlados por la fuente porque eran parte de la aplicación.

Gráfico Acíclico Dirigido

En un proyecto más reciente, surgió un enfoque diferente. Utilizo las classs que son nodos de un gráfico acíclico dirigido para encapsular las declaraciones para hacer actualizaciones específicas a la database para cada característica / corrección de errores / etc. Cada nodo tiene un atributo para declarar su nombre único y los nombres de los nodos de los que dependía. Estos attributes también se usan para search en el ensamblaje todos los nodos de actualización.

Un nodo raíz pnetworkingeterminado se proporciona como el nodo de dependencia para cualquier nodo sin dependencies, y este nodo contiene las instrucciones para crear la tabla migrationregister que enumera los nombres de los nodos que ya se han aplicado. Después de orderar todos los nodos en una list secuencial, se ejecutan sucesivamente, omitiendo los que ya están aplicados.

Todo esto está contenido en una aplicación separada de la aplicación principal, y están controlados por fuente en el mismo repository, de modo que cuando un desarrollador finaliza el trabajo en una característica y los cambios de la database asociados con ella, se comprometen juntos en el mismo set de cambios. Si extrae los cambios para la function, también extrae los cambios de la database. Además, la aplicación principal simplemente necesita una list de los nombres de nodo esperados. Cualquier extra o faltante, y sabe que la database no coincide.

Elegí este enfoque porque el proyecto a menudo tiene un desarrollo paralelo por múltiples desarrolladores, y cada desarrollador a veces tiene más de 1 cosa en desarrollo (desarrollo ramificado, a veces muy ramificado). Hacer malabares con los numbers de versión de la database fue bastante doloroso. Si todos comenzaron con la versión 37 y "Alice" comienza con algo y usa la versión 38 para cambiar su database, y "Bob" también comienza a trabajar para cambiar la database y también usa la versión 38, alguien tendrá que cambiar eventualmente . Entonces, digamos que Bob termina y empuja al server. Ahora Alice, cuando saca el set de cambios de Bob, tiene que cambiar la versión de las declaraciones a 39 y volver a establecer su versión de database en 37 para que se ejecuten los cambios de Bob, pero luego se ejecuta nuevamente .

Pero cuando todo lo que sucede cuando Alice saca el set de cambios de Bob es que simplemente hay un nuevo nodo de migration y otra línea en la list de nombres de nodo para verificar, las cosas simplemente funcionan.

Usamos Mercurial (distribuido) en lugar de SVN (cliente-server), por lo que es parte de por qué este enfoque funciona tan bien para nosotros.

Una solución fácil sería mantener un esquema completo en SVN (o cualquier biblioteca). Es decir, cada vez que cambie el esquema, ejecute MySQL "desc" para eliminar descripciones de todas las tablas, sobrescriba el último volcado de esquema con esto y luego confirme. Entonces, si ejecuta una versión diff, debería decirle qué cambió. Por supuesto, debe mantener todas las tablas en order alfabético (o en algún order pnetworkingecible).

Para un enfoque diferente: hace años trabajé en un proyecto para una aplicación de escritorio donde periódicamente enviaba nuevas versiones que podrían tener cambios de esquema, y ​​queríamos manejarlas sin la intervención del usuario. Entonces el progtwig tenía una descripción de qué esquema esperaba. Al inicio, realizó algunas llamadas de metadatos para verificar el esquema de la database que realmente tenía y las comparó con lo que esperaba. Si luego actualiza automáticamente el esquema para que coincida con lo que esperaba. Por lo general, cuando agregamos una nueva columna, simplemente podíamos dejar que comenzara nula o en blanco, por lo que esto requería prácticamente ningún esfuerzo de encoding una vez que obtuvimos la primera versión para funcionar. Cuando se requería alguna manipulación real para rellenar nuevos campos, teníamos que escribir código personalizado, pero eso era relativamente raro.

    Intereting Posts