neděle 31. ledna 2010

Verzování datového modelu a LiquiBase

Přidávání tabulek, sloupců, integritních omezení, přejmenovávání a štěpení tabulek, konfigurace vývojového, testovacího a produkčního prostředí... Je mnoho požadavků, které mají vliv na podobu datového modelu. V tomto blogu zkusím popsat běžné činnosti týkající se správy relačního datového modelu a stručně představit nástroj LiquiBase. Článek je volným pokračováním předchozího příspěvku Inicializace databázových dat prostředky Javy.

Různá prostředí kladou na správu datového modelu různé nároky - přizpůsobitelnost, nezávislost na konkrétní databázi, použitelnost pro testy nebo verzování. Krátce jsem je popsal v předchozím příspěvku. Jaké jsou běžné činnosti, které se správou datového modelu souvisí? Samozřejmě potřebujeme evidovat jakékoliv změny formou nějakého changelogu. V jistou chvíli je nutné změny z changelogu aplikovat na nějaký existující model - provést jeho aktualizaci. Někdy může být nutné naopak změny odstranit - provést jejich rollback. Při kvapném rozvoji datového modelu přijde vhod možnost porovnat dva modely. Při zavádění verzování je užitečná možnost reverzního vytvoření changelogu z existující databáze. A v neposlední řadě je dobré mít změny dobře zdokumentované.

Právě na tyto činnosti se zaměřili tvůrci nástroje LiquiBase. Než se k němu ale dostanu, popíšu napřed alternativní možnosti. Změny datového modelu se tradičně dají organizovat pomocí sql skriptů verzovaných nějakým scm nástrojem (jako je třeba Subversion). Pro každou změnu datového modelu se připraví samostatný sql skript, který se prostě vloží do scm systému. Jeho revize potom dovolí vybrat správnou množinu skriptů, které někdo ručně spustí. Některé firmy nedají dopustit na nástroje, které si vyvinuly svépomocí a které dovolí správu modelu alespoň částečně automatizovat. I správa datového modelu je doménou, na které se dá vydělávat a kterou řeší komerční nástroje.

LiquiBase

Na nových projektech se snažím používat LiquiBase. Je to nástroj, který mě zaujal svým úzkým zaměřením (neřeší nic, co by se správou datového modelu nesouviselo), snadnou přístupností (začlenění do vývojového procesu je jednoduché a přímočaré) a perfektní dokumentací. Nebudu suplovat dokumentaci LiquiBase a tutoriály přístupné z jeho webu, chci nástroj jenom stručně představit.

Changelog

Klíčový konceptem je changelog - xml soubor obsahující změny, zvané changesety. Změnou je třeba založení tabulky, přidání sloupce nebo vytvoření indexu. Každá změna je identifikovaná dvojicí (id,author). Changelog představuje historii změn datového modelu, ale neříká nic o tom, jak vypadají konkrétní instance modelu. Proto LiquiBase potřebuje, aby každý spravovaný mode obsahoval tabulku DatabaseChangeLog(id,author,filename,dateexecuted,...), která eviduje changesety aplikované na model.

Příklad changelogu:

<databaseChangeLog
  xmlns="http://www.liquibase.org/xml/ns/dbchangelog/1.6"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog/1.6
         http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-1.6.xsd">
    <changeSet id="1" author="bob">
        <createTable tableName="department">
            <column name="id" type="int">
                <constraints primaryKey="true" nullable="false"/>
            </column>
            <column name="name" type="varchar(50)">
                <constraints nullable="false"/>
            </column>
            <column name="active" type="boolean" defaultValue="1"/>
        </createTable>
    </changeSet>
</databaseChangeLog>

Changelog neobsahuje identifikaci databáze nebo chcete-li dialektu. Ten se zadává až při spouštění update a rollback příkazů. Pokud nemáme příliš specifické požadavky, můžeme tedy jeden changelog použít např. pro testovací MySQL nebo produkční Oracle. Vedle předdefinovaných příkazů mohou changesety obsahovat i sql skripty nebo odkazy na ně. 

Podporované jsou tyto databáze:
  • MySQL, PostgreSQL, Oracle, MS-SQL, Sybase Enterprise, Sybase Anywhere, DB2, Apache Derby, HSQL, H2, InterSystems Caché, Firebird, MaxDB / SAPDB, SQLite.
A tyto předdefinované operace (refactorings):
  • Structural Refactorings - Add Column, Rename Column, Modify Column, Drop Column, Alter Sequence, Create Table, Rename Table, Drop Table, Create View, Rename View, Drop View, Merge Columns, Create Stored Procedure
  • Data Quality Refactorings - Add Lookup Table, Add Not-Null Constraint, Remove Not-Null Constraint, Add Unique Constraint, Drop Unique Constraint, Create Sequence, Drop Sequence, Add Auto-Increment, Add Default Value, Drop Default Value
  • Referential Integrity Refactorings - Add Foreign Key Constraint, Drop Foreign Key Constraint, Add Primary Key Constraint, Drop Primary Key Constraint
  • Architectural Refactorings - Create Index, Drop Index
  • a další
LiquiBase je možné používat i na nepodporované databázi. Pokud pro ni nefungují některé z předdefinovaných operací, může changeset jednoduše obsahovat specifický sql kód.

Changelog můžeme udržovat ručně, vytvořit reverzně z existujícího modelu nebo použít podporu v IDE. Dobře funguje plugin pro IntelliJ IDEA a deklarovaná je i podpora pro Eclipse. Plugin pro Eclipse se mi ale nepodařilo zprovoznit.

Update a rollback

Základní příkazy pro aplikaci, resp. mazání změn, jsou update a rollback. Spouští se z příkazové řádky, z mavenu, z antu nebo třeba z IDE. Příkaz update aplikuje všechny nové changesety na existující model. To, jestli je daný changeset nový nebo již aplikovaný, pozná podle záznamů v tabulce DatabaseChangeLog. Příkaz rollback bere jako vstupní parametr identifikaci changesetu a všechny novější změny z modelu odstraní (pokud je to možné).

Dalšími užitečnými funkcemi jsou například
  • Diff - porovnání dvou databází a vytvoření changelogu.
  • DBDoc - vytvoří html manuál s popisem všech změn datového modelu.
  • nebo SQL výstup, který changlog převede na SQL skript.
Alternativy

migrate4j nebo dbmigrate jsou nástroje s podobným zaměřením jako LiquiBase. Vývojáři Ruby asi budou znát Ruby Migrations

Shrnutí

Článek chtěl popsat požadavky na evidenci změn datového modelu a ukázat, že s LiquiBase lze s malým úsilím změny organizovat lépe než jako "skripty v svn". Jak změny datového modelu organizujete vy? Máte bližší zkušenosti s nástrojem LiquiBase nebo jiným podobným? Podělte se o své názory v diskuzi pod článkem a zapojte se do hlasování.