Liquibase-Gestión De Cambios En Base De Datos

7
45130

Liquibase-Gestión De Cambios En Base De Datos

0. Índice de contenidos.

1. Introducción

Liquibase es un librería Open Source (bajo licencia Apache 2.0), totalmente independiente del DBMS, que nos permitirá realizar el seguimiento, gestión y aplicación de cambios en el modelo de datos. Hoy en día, en cualquier desarrollo profesional de software no puede faltar un sistema de control de versiones. Esta práctica esta totalmente arraigada en los desarroladores que, sin embargo, en muy pocas ocasiones la usamos en cuanto al modelo de datos se refiere.

En esta ocasión os mostramos como hacer uso de esta librería para incorporar un control de cambios de la base de datos a vuestros desarrollos, lo que
os proporcionará una gran sensación de control y os permitirá mantener un histórico de cada una de las modificaciones sobre el modelo de datos.

Una de las prácticas habituales en los desarrollos, es la creación de script sql incrementales. Con lo que comenzamos con script de creación de tablas, script
de inserción de datos etc etc … y, a medida que avanza el desarrollo, cada uno de los desarrolladores va creando scripts con las modificaciones oportunas que le exige la tarea que está llevando a cabo. Esta práctica hace del proceso de cambios de base de datos un proceso totalmente manual, que puede llevar a confusiones, sobre todo debido a que es muy posible no saber que scripts se han ejecutado y cuales faltan por ejecutar en cada uno de los entornos que estemos manejando.

Liquibase es una librería diseñada para trabajar principalmente desde línea de comandos, pero también se integra muy fácilmente con Maven y Spring. Esta fácil
integración con los frameworks mencionados es la característica de liquibase que más me llamó la atención, ya que nos va a permitir automatizar el proceso de cambios en base de datos, con lo que no tendremos que preocuparnos de estar ejecutando diferentes scripts, ni el orden en que se ejecutan. Además cada miembro del equipo de desarrollo dispondrá de información sobre que cambios se han realizado y quien los ha realizado.

2. Entorno

El tutorial está escrito usando el siguiente entorno:

  • Hardware : Portátil Mac Book Pro 15″ (2,6 Ghz Intel Core i7, 4 GB DDR3)
  • Sistema Operativo:Mac OS X Snow Leopard 10.6.4
  • Liquibase 1.9.5
  • MySQL 5.0.5

3. Puesta en marcha

Antes de empezar me gustaría dejaros el enlace a la página oficial de la librería. Liquibase. En ella podreís encontrar toda la documentación disponible sobre el proyecto ya que el objetivo del tutorial es daros a conocer esta librería y enseñaros como ponerla en marcha. Sin embargo, si decidís hacer uso de la misma seguramente necesitareis acceder a información más concreta para los casos específicos con los que esteis trabajando.

Descargamos Liquibase desde aquí.
Descomprimimos el contenido del fichero descargado y abrimos el terminal.

Un paso opcional, aunque muy recomendable es editar el fichero .bash_profile incluyendo la ruta donde hayamos descomprimido el
fichero descargado. Esto es simplemente para que cada vez que queramos ejecutar un comando con liquibase no tengamos que ir hasta
el directorio donde lo hayamos descomprimido.
En mi caso el path sería el siguiente:

export PATH="$PATH:/Developer/Applications/liquibase-1.9.5" 

Reiniciamos el Terminal y comprobamos que Liquibase está preparado para comenzar a trabajar.
Para ello solo tenemos que teclear liquibase en el terminal. Si nos aparece un listado con los comandos disponibles es que liquibase está correctamente
configurado.

4. Construyendo el Change-Logs

El fichero chagelogs.xml es la base sobre la que trabaja Liquibase para saber cuales son los cambios que se deben realizar sobre la base de datos. A continuación
os muestro un ejemplo:

  

  • Liquibase Tags

    Liquibase nos proporciona una serie de etiquetas con las que construir nuestro conjunto de cambios. Lo cierto es que es bastante intuitivo, y
    como veremos a lo largo del tutorial, tanto el nombre de las etiquetas, como el nombre de los atributos de las mismas nos van a dar pistas sobre cual es la operación que van a realizar.

    En un primer momento, el hecho de tener que aprender un nuevo «lenguaje», distinto de SQL para realizar cambios en la base de datos es una característica de liquibase que no me gustó en un principio. Principalmente dudaba de si con las etiquetas que Liquibase nos proporciona, se podrían realizar todos los cambios que con SQL estamos acostumbrados a realizar, sobre todo aquellos cambios que pudiesen resultar más complejos.

    Después de realizar las primeras pruebas las dudas se disiparon. Liquibase nos va a permitir en todo momento seguir trabajando con script SQL, con la ventaja añadida de que todos lo cambios quedaran reflejados en el histórico.

    • <databaseChangeLog>

      Es la etiqueta raiz a partir de la cual Liquibase comienza a analizar y ejecutar cada uno de los cambios.

    • <preConditions>

      Comprueba que se cumplan cada una de las condiciones definidas. Si alguna de las precondiciones fallase Liquibase acabaría con un mensaje de error donde se indicará cual ha sido la condición que ha fallado. Las precondiciones son muy útiles para comprobar por ejemplo, el tipo de base de datos y el usuario que realizará las distintas modificaciones.

    • <changeSet>

      Con esta etiqueta se definen cada uno de los cambios que se realizan en la base de datos. Por cada changeSet se insertará una nueva fila en el histórico de cambios. Por ello es recomendable hacer un solo cambio por cada chageSet, teniendo en cuenta que se permiten más y puede tener sentido por ejemplo, si se van ha insertar varias filas que forman parte de una misma transacción.

      Un changeset es un conjunto de cambios que se identifica por dos atributos, el «id» y el «author». Si solo se utilizase el «id» para identificar un changeset, sería demasiado facil duplicar un conjunto de cambios de manera accidental, sobre todo cuando se está trabajando dentro de un grupo de desarrollo.

      Esta es una de las etiquetas más importantes y que más utilizaremos con Liquibase. En su interior usaremos otro buen conjunto de etiquetas para ir definiendo cada uno de los cambios de la base de datos. En la sección Available Database Refactorings del manual encontramos la información sobre cada una de las etiquetas disponibles para usar en un changeSet y conformar un conjunto de cambios. En este momento solo os enumero alguna de las más utilizadas:

      • <createTable>

        Nos permite crear nueva tabla en base de datos.

          
        
        
      • <dropTable>

        Nos permite eliminar una tabla en base de datos.

        
        
      • <addColumn>

        Nos permite añadir una columna a una tabla.

          
        
        
      • <renameColumn>

        Nos permite renombrar una columna de una tabla.

        
        
      • <modifyColumn>

        Nos permite modificar una columna de una tabla.

          
        
        
      • <dropColumn>

        Nos permite eliminar una columna de una tabla.

        
        
      • <sqlFile>

        Nos permite ejecutar un script SQL dentro del proceso de migración de liquibase.

         
        
    • <include>

      El principal uso de esta etiqueta es poder romper el fichero principal de cambios (changelogs.xml) en pedazos más manejables. Esto supone una gran ventaja ya que a medida que avanzan los desarrollos el número de modificaciones suele ser muy elevado.

      Una buena práctica es trabajar con un fichero de cambios por sprint o por versión, en función de las necesidades. Algo como :

        
      
      
    • <includeAll>

      Esta etiqueta es muy similar a la anterior, pero en vez de incluir un listado de ficheros específicos, se indica un directorio en el que se incluyen todos los archivos *.xml y *.sql que conformarán nuestro conjunto de cambios. Todos los archivos que se encuentren en el directorio indicadado se ejecutan en orden alfabético. Según la documentación el uso de esta etiqueta puede provocar errores futuros, posiblemente porque el orden de ejecución puede provocar conflictos en nuestra base de datos. Por eso es recomendable usar <include>

    • <context>

      Esta etiqueta básicamente nos permite distinguir entre los distintos entornos de ejecución. Normalmente en cualquier desarrollo suele haber distintos entornos en los que la aplicación es ejecutada (desarrollo, preproducción y producción por ejemplo). Mediante esta etiqueta podremos indicar a un changeSet a que entorno de ejecución pertenece, después, al ejecutar liquibase, indicaremos por parámetro cual es el entorno en el que se realizarán los cambios, de esta manera Liquibase solo ejecutará los changeSet que pertenezcan al entorno indicado como parámetro.

        
      
      

5. Liquibase-Funcionalidad.

A continuación os muestro cuales son las funciones que podremos realizar con Liquibase:

  • Update

    El update es la funcionalidad principal de la librería. Nos va a permitir aplicar los cambios en base de datos en función al changelogs.xml generado con anterioridad.
    Como ya hemos visto, cada uno de los cambios viene definido por los changeset, que se identifican por el author y el id. Cada vez que se ejecuta un update
    Liquibase verifica cada uno de los identificadores de los changeset. Si el identificador no existe se inserta una nueva fila en el histórico de cambios (DATABASECHANGELOG) que
    contiene el identificador del chageset más un MD5Sum. De esta manera Liquibase puede identificar de manera unívoca cada uno de los cambios realizados.

    Si el identificador del changeset ya existe en el histórico, se compara el MD5Sum actual con el que ya existe en el histórico. Si los MD5Sum son diferentes Liquibase mostrará un error para avisarnos de que se ha modificado de manera inesperada un changeset especifico. Esto es algo a tener en cuenta cuando empezamos a trabajar con Liquibase ya que nos puede dar algún que otro problema, por ejemplo:

    Creamos un changeset para crear una tabla:

      
    
    

    Tras realizar el update el chageset se ejecuta correctamente pero nos damos cuenta de que nos hemos equivocado en el nombre de una de las columnas. Es fácil caer en el error de modificar el changeset directamente, lo que nos provocará el error anteriormente mencionado (Los MD5Sum son distintos).

    Por tanto si os pasa algo así solo hay que crear un nuevo changeset con el cambio que queremos realizar. Por ejemplo:

      
    
    
    • Ejecutando Update

      La primera vez que ejecutemos este comando contra una base de datos Liquibase creará dos tablas en el schema correspondiente. Una llamada DATABASECHAGELOG y otra DATABASECHAGELOGLOCK. La primera es donde se guardaran todos los cambios y la segunda es usada por Liquibase para controlar que solo se realicen un conjunto de cambios al mismo tiempo.

      Una vez realizada esta aclaración desde la línea de comandos ejecutamos:

      liquibase  
      --driver=com.mysql.jdbc.Driver  
                          --classpath=/Users/sgdiaz/mysql-connector-java-5.0.5.jar  
         --changeLogFile=/Users/sgdiaz/changelog.xml   
                          --url="jdbc:mysql://localhost:3306/liquibase"   
                          --username=liquibase   
                          --password=liquibase   
                          update  
      

      Si nos vamos a la base de datos podremos comprobar que nos ha creado las dos tablas propias de Liquibase así como la tabla que le hemos indicado en el changelog.xml. El conjunto de cambios que he usado es el del ejemplo al inicio del tutorial.

  • Rollback

    Liquibase nos va a permitir deshacer los cambios realizados en base de datos, ya sea de manera automática o de manera manual. Algunos de los tags de Liquibase como
    <createTable>, <addColumn>, <renameColumn> llevan implícitamente un rollback, lo que quiere decir que, si por algún motivo se produce un error, se desharan los cambios de manera automática.

    Otros tags como <dropTable> o <insertData> no llevan el rollback implícito por lo que habrá que definirlo de manera manual. Vemos un ejemplo:

      
    
                     delete from Usuarios where id=1  
    
    
    • Diffs

      Aunque la mejor manera de controlar los cambios en la base de datos es mediente la adición de conjuntos de cambios durante el desarrollo, hay ocasiones en que será muy valioso poder realizar diffs de distintas bases de datos, sobre todo cuando se está llegando al final del proyecto, pudiendo así comprobar que todos los cambios necesarios están incluidos en el changelog. Es importante tener en cuenta que la ejecución del diff solo está disponible desde la línea de comandos.

      En la actualidad Liquibase realiza las siguientes comparaciones:

      -Diferencias de versión
      -Ausencia de tablas
      -Ausencia de vistas
      -Ausencia de columns
      -Ausencia de primary keys
      -Ausencia de unique constraints
      -Ausencia de foreign Keys
      -Ausencia de secuencias
      -Ausencia de índices
      -Diferencias en la definición de las columnas (data type, auto-increment, etc.)
      -Diferencias en la definición de las vistas

      Desde línea de comandos ejecutamos:

      El resultado es el siguiente:

 

 

  • Generate Change Logs

     

    Esta funcionalidad de Liquibase es muy útil cuando empezamos a trabajar con una base de datos que ya tiene creadas una serie de tablas. De tal manera que podremos generar nuestro changelogs.xml a partir del modelo de datos existente. Eso si, hay que tener en cuenta que esta funcionalidad tiene actualmente algunas limitaciones, como por ejemplo que no exporta procedimientos almacenados, funciones y triggers.

     

    liquibase  
    --driver=com.mysql.jdbc.Driver  
                --classpath=/Users/sgdiaz/mysql-connector-java-5.0.5.jar  
       --changeLogFile=/Users/sgdiaz/changelog.xml   
                --url="jdbc:mysql://localhost:3306/liquibase"   
                --username=liquibase   
                --password=liquibase   
                generateChangeLog
    
  • DBDoc

    Utilizando la información existente en el histórico y una base de datos existente, Liquibase puede generar documentación sobre los cambios realizados en base de datos.La documentación generada es al estilo JavaDoc.

    liquibase  
    --driver=com.mysql.jdbc.Driver  
                --classpath=/Users/sgdiaz/mysql-connector-java-5.0.5.jar  
       --changeLogFile=/Users/sgdiaz/changelog.xml   
                --url="jdbc:mysql://localhost:3306/liquibase"   
                --username=liquibase   
                --password=liquibase   
                dbDoc /Users/sgdiaz 
    
  • SQL Output

    Depenpdiendo del proceso de desarrollo y de las necesidades que tengamos a la hora de liberar versiones, es posible que no queramos utilizar Liquibase para realizar los cambios sobre la base de datos de manera directa.

    Por esta razón tanto los comandos Update y Rollback tienen un «sql output» de modo que no se ejecute nada contra la base de datos sino que se genera un script.sql que el desarrollador ejecutará manualmente.

    liquibase  
    --driver=com.mysql.jdbc.Driver  
                --classpath=/Users/sgdiaz/mysql-connector-java-5.0.5.jar  
       --changeLogFile=/Users/sgdiaz/changelog.xml   
                --url="jdbc:mysql://localhost:3306/liquibase"   
                --username=liquibase   
                --password=liquibase   
                updateSQL > /Users/sgdiaz/script.sql
    

6. Integración con Spring y Maven.

La fácil integración de Liquibase con Spring y Maven hacen que el uso de la librería sea una autentica maravilla. A continuación vemos como necesitamos solo dos pasos para correr Liquibase con Spring:

  • 1. Añadimos la dependencia correspondiente al pom.xml:
      
            org.liquibase  
            liquibase-core  
                 1.9.5  
    
    
  • 2. Añadimos en el fichero de configuración de Spring (applicationContext.xml):
      
    
           
    
    

Con estos dos sencillos pasos estaremos ejecutando un Update con Liquibase cada vez que despleguemos nuestra aplicación en el servidor, y tengo que decir que resulta de una gran comodidad ya que nos olvidamos por completo de la ejecución de los típicos script.sql cada vez que se realizamos una nueva instalación.

Para integrar la librería con Maven también es muy sencillo. Lo vemos a continuación:

Incluimos en el fichero de dependencias:

  
         mysql  
         mysql-connector-java  
           
         ${mysql-version}  

Para configurar correctamente el plugin de Maven es necesario tener la dependencia con la base de datos que estemos utilizando. Después solo incluimos el propio plugin.

  
    org.liquibase  
    liquibase-plugin  
    1.6.1.0  

        package  

          classpath:changelog.xml  
          com.mysql.jdbc.Driver  
          jdbc:mysql://localhost:3306/liquibase  
          liquibase  
          liquibase  

          update  

Con esta configuración estamos indicando que cada vez que se ejecute, la fase de package Liquibase realice un Update en el que se realizarán todos los cambios indicados en el fichero de cambios.

7. Conclusiones.

Personalmente creo que esta librería es una herramienta muy útil que da un valor añadido a los desarrollos. Tened en cuenta que llevar control estricto sobre el modelo de datos es algo muy importante que no siempre se realiza con la rigurosidad que requiere. Por tanto Liquibase puede convertirse en la herramienta perfecta para llevar acabo esta tarea.

Sin embargo sois vosotros los que tendreis que decidir si Liquibase encaja en vuestros desarrollos. Mi consejo es que probeis ya que el impacto de usar Liquibase y no usarlo es mínimo y las ventajas son muchas.

Un saludo.

Saúl García Díaz

7 COMENTARIOS

  1. Excelente manual.
    Una pregunta, cada ves que se realiza un cambio en la base de datos y queremos almacenar los cambios, es necesario ejecutar el script.
    Alguna forma para que al trabajar sobre jsp, cada ves que se realice un cambio en la DB de MySql quede registrado en los changelog, sin necesidad de trabajar con otra herramienta como maven?

  2. Buen tutorial, lo he probado en BD Firebird funcional salvo con algunos problemillas pro ejemplo al ejecutar un dropTable, si no existe se trunca la ejecución del changeLog, intente poner el rollback pero aun así no funciono.
    Saludos desde Oaxaca, México

  3. Bueno he tenido vasta experiencia con la herramienta y poder decir que ayuda bastante y mucho más cuando se tiene diferente ambiente Dev, QA, Pro en estos casos un controlador de versiones, basta decir que estaba buscando un tutorial donde yo pueda usar liquibase en un DBMS que ya está en funcionamiento.

DEJA UNA RESPUESTA

Por favor ingrese su comentario!

He leído y acepto la política de privacidad

Por favor ingrese su nombre aquí

Información básica acerca de la protección de datos

  • Responsable:
  • Finalidad:
  • Legitimación:
  • Destinatarios:
  • Derechos:
  • Más información: Puedes ampliar información acerca de la protección de datos en el siguiente enlace:política de privacidad