paint-brush
Usando enlaces de Git con MySQLpor@yuridanilov
4,711 lecturas
4,711 lecturas

Usando enlaces de Git con MySQL

por Yuri Danilov7m2023/09/30
Read on Terminal Reader

Demasiado Largo; Para Leer

Crear base de datos de prueba Crear git hook después de la recepción Ejecutar scripts SQL al presionar
featured image - Usando enlaces de Git con MySQL
Yuri Danilov HackerNoon profile picture
0-item
1-item

Los sistemas de control de versiones, y Git en particular, son herramientas esenciales para rastrear los cambios de código, colaborar con su equipo y garantizar la estabilidad de su base de código. Si bien Git está diseñado principalmente para código fuente, también puedes usarlo en combinación con bases de datos MySQL para control de versiones y gestión de cambios de esquema.


En este artículo, exploraremos cómo integrar Git con MySQL para el control de versiones usando enlaces de Git, con ejemplos específicos en un formato de guía. Todos los scripts que figuran en los listados son completamente funcionales y completos. Puede reproducirlos secuencialmente en su entorno de prueba.


En primer lugar, creemos una base de datos y un usuario de prueba:

 create database testdb_remote; create user 'user_remote'@'localhost' identified WITH mysql_native_password by 'remote123'; grant all on testdb_remote.* to 'user_remote'@'localhost'; 


Creando una base de datos de prueba


A continuación, crearemos un repositorio remoto. Este puede ser un repositorio en cualquier servidor remoto, pero para simplificar, lo crearemos localmente. Para facilitar la ejecución de comandos, utilizo git bash. Mi máquina local ya tiene una carpeta git, así que la uso:

 cd /c/git mkdir testdb.remote cd testdb.remote git init --bare 


Crear un repositorio remoto

Y crea un repositorio local como un clon del remoto:

 cd /c/git git clone /c/git/testdb.remote testdb.local cd testdb.local git ls-files 


Creando un repositorio local


No hay archivos en el repositorio; creemos uno y enviemos nuestros cambios al repositorio remoto:

 echo "Test DB repo" > readme.md git status git add . git commit -m "1st commit" git push 


primer empujón


Comprobemos el contenido del repositorio remoto:

 cd /c/git/testdb.remote git ls-tree --full-tree -r HEAD 


Archivo en repositorio remoto


Hay una carpeta de ganchos en el repositorio remoto, que contiene varios archivos con ejemplos:

 ls -1 /c/git/testdb.remote/hooks 


Ganchos de muestra


Los ganchos son scripts que se ejecutan cuando ocurren eventos específicos. Git tiene ganchos del lado del cliente y del lado del servidor. Los enlaces del lado del cliente se activan mediante operaciones como la confirmación y la fusión. Los enlaces del lado del servidor se ejecutan en operaciones de red, como la recepción de confirmaciones enviadas. Los ganchos se describen en detalle aquí . Existen diferentes opciones para implementar la lógica; Daré un ejemplo del uso del gancho del lado del servidor posterior a la recepción .


En la carpeta de ganchos, necesitamos crear un archivo llamado "post-receive", este es un script bash normal:

 #!/bin/sh while read oval nval ref do echo List of files changed in the commit: git diff --name-only $oval $nval done


El script anterior se ejecutará en el servidor cada vez que se complete con éxito una inserción y generará una lista de archivos modificados. Comprobemos cómo funciona agregando una línea al archivo readme.md y enviando los cambios al repositorio remoto:

 cd /c/git/testdb.local echo "New line" >> readme.md git add . git commit -m "Line added" git push 


Prueba del script de enlace posterior a la recepción


Puede ver que al ejecutar el comando git push, la salida ahora contiene líneas que comienzan con remote: esta es la salida del script posterior a la recepción que se ejecutó en el servidor.

Hablando de cambios básicos, los archivos se pueden agregar, modificar y eliminar. Puede adoptar diferentes enfoques sobre cómo aplicar estos cambios a la base de datos:


  1. Realice cambios en la base de datos solo cuando agregue nuevos archivos. En este caso, puede guardar todos los cambios de una tarea específica en un solo archivo. Este archivo puede contener el nombre de la tarea del sistema de seguimiento de errores. Puede que esto no sea muy conveniente durante el desarrollo, pero dichos cambios son más fáciles de manejar.
  2. Mantenga un archivo separado en el repositorio para cada objeto (tablas, procedimientos) y aplique cambios a la base de datos al cambiar o agregar archivos.
  3. Un enfoque más completo es crear una carpeta separada para cada tarea (solicitud de cambio) y colocar en ella los archivos que deben ejecutarse como parte de la instalación de una versión determinada. Al mismo tiempo, cree un archivo adicional que describa la lista de archivos y el orden en que deben instalarse. Este enfoque es más flexible pero, al mismo tiempo, más complejo tanto para el desarrollo como para la implementación del pipeline.


Supongamos que eligió la segunda opción, por lo que necesita ejecutar archivos que se agregaron o modificaron. Podemos filtrar dichos archivos como se describe aquí agregando el parámetro --diff-filter=AM :

 #!/bin/sh while read oval nval ref do echo List of files added or changed in the commit: git diff --name-only --diff-filter=AM $oval $nval done


Agregue algunos archivos y cambie también el archivo readme.md nuevamente:

 echo "SELECT 1;" > test1.sql echo "SELECT 2;" > test2.sql echo "SELECT 3;" > test3.sql echo "New line 2" >> readme.md git add . git commit -m "New files" git push


La salida del script de enlace contiene 4 archivos:

Lista de todos los archivos modificados


Editamos los archivos test1.sql y readme.md, eliminamos test2.sql y agregamos otro archivo:

 echo "SELECT 11;" > test1.sql echo "New line 2" >> readme.md rm test2.sql echo "SELECT 4;" > test4.sql git add . git commit -m "Modify, remove and add" git push


Sólo se muestran los archivos modificados y agregados:

Sólo archivos agregados o modificados


Nuestro objetivo es ejecutar scripts SQL después de cada envío exitoso, por lo que necesitamos filtrar archivos solo de este tipo; en nuestro caso pondremos como requisito que todos tengan la extensión “.sql”. Para filtrar, agregue el parámetro -- "*.sql" al comando git diff :

 #!/bin/sh while read oval nval ref do echo List of files added or changed in the commit: git diff --name-only --diff-filter=AM $oval $nval -- "*.sql" done


Para ejecutar scripts, también debemos poder conectarnos a la base de datos. Para ello crearemos credenciales y probaremos la conexión:

 mysql_config_editor set --login-path=testdb_remote --host=localhost --port=3306 --user=user_remote --password mysql --login-path=testdb_remote --database=testdb_remote 


Creando créditos para MySQL


Modifique nuestro script para recorrer los archivos “.sql”, ejecute cada archivo y verifique el resultado. También necesitamos ordenar la salida de la lista para ejecutar los archivos en el orden requerido. Con el comando git show, mostramos el contenido del script SQL y lo pasamos a través de la tubería para que MySQL lo ejecute .

La variable “$?” contendrá 0 si el script SQL se ejecutó exitosamente y otro valor si hubo un error:

 #!/bin/sh while read oval nval ref do echo List of files added or changed in the commit: for file in $(git diff --name-only --diff-filter=AM $oval $nval -- "*.sql" | sort); do git show master:${file} | mysql --login-path=testdb_remote --database=testdb_remote echo "FILE: ${file} - result $?" done done


Realice una prueba más: elimine todos los archivos “.sql” creados anteriormente y cree scripts para:


  • creación de mesa
  • insertando datos en la tabla
  • crear un procedimiento para recibir datos de la tabla
  • script que contiene un error


También necesitamos agregar un prefijo (1_, 2_, etc.) a cada nombre de archivo para garantizar el orden de ejecución deseado de los archivos:

 rm *.sql echo "DB Initialization" >> readme.md echo " DROP TABLE IF EXISTS customers; CREATE TABLE customers ( id int UNSIGNED NOT NULL AUTO_INCREMENT, name varchar(255) DEFAULT NULL, PRIMARY KEY (id) ); " > 1_customers.sql echo " INSERT INTO customers (id, name) VALUES (1, 'John Doe'), (2, 'Jane Smith') AS new ON DUPLICATE KEY UPDATE customers.name = new.name; " > 2_customers_init.sql echo " DROP PROCEDURE IF EXISTS get_customer; DELIMITER $$ CREATE PROCEDURE get_customer(IN customer_id int UNSIGNED) BEGIN SELECT c.id, c.name FROM customers c WHERE c.id = customer_id; END $$ " > 3_get_customer.sql echo "SELECT FROM customers;" > 4_error_select.sql ls -1


Entonces tenemos cuatro archivos “.sql” que deben ejecutarse:

Lista de archivos

Realizamos cambios en el repositorio:

Sólo se ejecutan archivos SQL


Y vemos que cuando se realiza git push , los archivos se ejecutan secuencialmente y se muestra el resultado de la ejecución (código de salida del comando MySQL) de cada archivo. El archivo “4_error_select.sql” contiene un error de sintaxis, por lo que el resultado de su ejecución es 1.


Y por último, revisemos lo que tenemos en la base de datos:

 mysql --login-path=testdb_remote --database=testdb_remote show tables; call get_customer(1); call get_customer(2); 


Probar objetos creados en DB


Como puede ver, la tabla y el procedimiento se crearon en la base de datos remota. El procedimiento se ejecuta exitosamente y devuelve datos.


Para mejorar la legibilidad de la salida del script de enlace, puede suprimir la salida de la CLI de MySQL o redirigirla a un archivo de registro. También puede analizar el resultado de la ejecución del comando MySQL y agregar más lógica al script de enlace.


Por ejemplo, puede ejecutar scripts SQL en una base de datos de prueba y luego ejecutar algunas pruebas en ella (como lo describí aquí ). Si las pruebas se completan con éxito en la base de datos de prueba, ejecute scripts SQL en la base de datos de producción y probablemente también ejecute algunas pruebas en ella.

Al analizar los resultados de cada paso, puede crear canalizaciones de cualquier configuración.


Por supuesto, cada enfoque tiene una serie de ventajas y limitaciones. Con el segundo enfoque, es necesario asegurar el orden en el que se ejecutan los scripts porque no podemos, por ejemplo, insertar datos en una tabla hasta que se cree. También es necesario asegurarse de poder volver a ejecutar scripts, es decir, manejar correctamente situaciones en las que el objeto que se está creando ya está en la base de datos o la base de datos ya contiene los datos que se van a agregar.


Cuando se utiliza un sistema de control de versiones, el proceso de desarrollo se vuelve un poco más complicado porque es necesario formalizar adicionalmente los cambios en scripts de un formato predeterminado. Sin embargo, puede lograr cierta flexibilidad utilizando un archivo de instalación.


La principal ventaja de la técnica descrita es la implementación del control de versiones en la base de datos con muy poco esfuerzo, así como la capacidad de implementar pipelines CI/CD .

Para evaluar si esto podría resultarle útil, puede comenzar preguntándose: ¿Con qué frecuencia escribe código directamente en producción?