Wersjonowanie baz danych
podczas developmentu

Liquibase
Piotr Pelczar
me@athlan.pl
Piotr ’Athlan’ Pelczar
Freelancer: vgroup.pl, athlan.pl
goldenline.pl/piotr-pelczar
me@athlan.pl
Agenda
1.
2.
3.
4.
5.
6.
7.
8.
9.

Problem wersjonowania struktur baz danych
Przedstawienie narzędzia Liquibase
Instalacja
Pierwszy zrzut bazy, tworzenie tagów
Database diff, tag
Rollback
Preconditions
Dobre praktyki
Integracja z Maven i Eclipse
Problem
• Baza danych musi być integralna podczas
developmentu.
• Jak utrzymać jej integralność?
• Jak pozbyć się problemu supportowania
developerów?
• Problem branchowania i mergeowania zmian
wprowadzanych podczas równoległego rozwoju
aplikacji.
Czym jest Liquibase?
•
•
•
•

Niezależna od bazy danych biblioteka.
OpenSource.
Dostępna z linii poleceń.
Do śledzenia i zarządzania zmianami w bazie
danych.
• Zmiany są zapisywane w plikach XML.
Wspierane bazy danych
•
•
•
•
•
•
•
•

MySQL
PostgreSQL
Oracle
MS-SQL
Sybase Enterprise
Sybase Anywhere
DB2
Apache Derby

http://www.liquibase.org/databases
Warto się zapoznać z issues.

•
•
•
•
•
•
•

HSQL
H2
Informix
InterSystems Caché
Firebird
SAPDB
SQLite
Format zmian
•
•
•
•

Jako plik XML
Obsługuje ponad 40 rodzajów zmian
W tym raw SQL, co jest otwartą furktą
Można uruchamiać komendy shell

http://www.liquibase.org/manual/refactoring_commands
Format zmian
Format zmian
• Zmiany są również przechowywane lokalnie w
bazie danych w tabeli databasechangelog
Współbieżność pracy
• Współbieżność jest zagwarantowana poprzez
wpisy w tabeli databasechangeloglock
Uruchamianie Liquibase
Możliwość uruchomienia Liquibase z poziomu:
•
•
•
•
•
•
•

Ant
Maven
Spring Framework (jako bean w kontekście)
Grails
Servlet Listener
Command Line
Integracja z Hibernate
Instalacja
1. http://www.liquibase.org/download
2. Rozpakowujemy
3. Pobieramy odpowiedni driver JDBC do bazy
danych, np. postgresql-9.1-902.jdbc4.jar
Instalacja
4. W bieżącym katalogu tworzymy pusty
liquibase.properties z wpisem:
classpath=D:ProgramsLiquibase
postgresql-9.1-902.jdbc4.jar
Nadpisuje on wartości z linii poleceń, można
zmienić lokalizację za pomocą flagi -defaultsFile
http://www.liquibase.org/manual/command_line#using_a_li
quibaseproperties_file
Wymagania
1. Java 1.5 lub nowsza
2. Poprawnie skonfigurowany classpath oraz
JAVA_HOME
3. Tak, aby Java była dostępna z polecenia:
java -version
4. Liquibase jest uruchamiane jako archiwum
JAR:
java -jar liquibase.jar
Po rozpakowaniu
Pierwszy zrzut bazy danych
liquibase
--url=jdbc:postgresql://localhost:5432/
handlowcy
--username postgres
--password root
--changeLogFile="schema.xml"
generateChangeLog
http://www.liquibase.org/manual/generating_changelogs
Pierwszy zrzut bazy danych
Ograniczenia, w sposób automatyczny nie są
zrzucane:
• Procedury składowane
• Funkcje
• Triggey
• Jest możliwość wykonywania swoich zapytań
SQL, ale nie będą przenośne.
http://www.liquibase.org/manual/generating_changelogs
Załadowanie schematu bazy
liquibase
--url=jdbc:postgresql://localhost:5432/
handlowcy_dev
--username postgres
--password root
--changeLogFile="schema.xml"
update
Wygenerowanie zapytań SQL
liquibase
--url=jdbc:postgresql://localhost:5432/
handlowcy_dev
--username postgres
--password root
--changeLogFile="schema.xml"
updateSQL > changes.sql
Nadeszły zmiany, diff
Sprawdzenie zmian, które nastąpiły:
liquibase
--url=jdbc:postgresql://…
--username postgres
--password root
--referenceUrl=jdbc:postgresql://…
--referenceUsername postgres
--referencePassword root
diff
Nadeszły zmiany, diff
Generujemy zmiany, diffChangeLog
liquibase
--url=jdbc:postgresql://…
--username postgres
--password root
--referenceUrl=jdbc:postgresql://…
--referenceUsername postgres
--referencePassword root
--changeLogFile=changelog-DATE-ath.xml
diffChangeLog
Diff danych
liquibase
--url=jdbc:postgresql://…
--username postgres
--password root
--referenceUrl=jdbc:postgresql://…
--referenceUsername postgres
--referencePassword root
--changeLogFile=changelog-DATE-ath.xml
--diffTypes=data
diffChangeLog
Diff uwagi
Diff obsługuje:
• Missing/unexpected tables, views, columns
• Missing/unexpected primary keys, unique
constraints
• Missing/unexpected foreign Keys
• Missing/unexpected sequences, indexes
• Column definition differences (data type, autoincrement, etc.)
• View definition differences
• Data differences (limited), not checked by
default
Nadeszły zmiany, diff
Diff nie obsługuje:
• Non-foreign key constraints (check, etc)
• Stored Procedures
• Data type length*
* Testowano: Zmiany długości varchar w
PostgreSQL są wykrywane.
Nadeszły zmiany, diff
• Ważnym jest, żeby dobrze interpretować „reference”.
Z naszej perspektywy baza produkcyjna jest główną, a
rererence jest developerska.
Jeżeli odwrócimy, naturalną konsekwencją jest
wygenerowanie DROP’ów zamiast CREATE’ów.
• Umieszczanie daty i nazwy dewelopera w nazwach
plików changelogów to dobry nawyk:
2012-11-24-athlan.xml.
• Przy zbiorczych change’ach pliki te jednoznacznie są
identyfikowane nie tylko w Liquibase, ale na
repozytorium git czy SVN, można je łatwiej mergeować.
Nadeszły zmiany, diff
• Raz wykonany changeSet już nigdy nie zostanie
powtórzony (identyfikowany po author oraz id).
• Nie ma poprawiania XML na repo.
Tagowanie bazy danych
1. W pliku XML
<tagDatabase tag="NAZWA"/>
2. Z poziomu linii poleceń

liquibase
--url=jdbc:postgresql://…
--username postgres
--password root
tag NAZWA
Rollback
Tryb

Komenda

Tryb SQL

Do taga

rollback
<tag>

rollbackSQL
<tag>

Data

rollbackToDate
<date>

rollbackToDateSQL
<date>

Ilość
changeset’ów

rollbackCount
<number>

rollbackCountSQL
<number>
Rollback
liquibase
--url=jdbc:postgresql://…
--username postgres
--password root
rollback tag

rollbackSQL tag > rollback.sql
Rollback
• Większość operacji ma komplementarne sobie
operacje odwrotne.
• Jeżeli nie mają, lub chcemy podjąć inne akcje,
do changeset’a dodajemy tag <rollback>
• Są zapisywane w bazie danych.
Rollback
Rollback
• Przykładowy procedure
Preconditions
Warunki, które muszą być spełnione, aby nastąpił
cały zestaw changeset’ów lub pojedynczy z nich.
Przydają się, gdy:
• Osoba przygotowująca changelog ma jakieś
założenia.
• Zapewnia ich przestrzealność.
• Umożliwia sprawdzenie danch, bądź
parametrów.
• Decyduje, które chengesety są uruchamiane, a
które nie.
Preconditions
Preconditions
Preconditions
Możliwe preconditions:
•
•
•
•
•
•
•

columnExists
•
tableExists
•
•
viewExists
•
indexExists
sequenceExists
primaryKeyExistsdbms
runningAs

changeSetExecuted
sqlCheck
changeLogPropertyDefined
customPrecondition
(className
implementuje interfejs
liquibase.precondition.Cust
omPrecondition)
Dobre praktyki
1. Trzymaj changelog’i spięte <include> zawarte
w master.xml i wykonuj master’a
Integracja z Maven: pom.xml
• Tworzymy główny pom.xml
• Przykład dotyczy modułu common-model
Integracja z Maven: pom.xml
Integracja z Maven: pom.xml
Integracja z Maven: pom.xml
Kompilacja Maven z changesetami:
mvn install:liquibase
Pytania?
1.
2.
3.
4.
5.
6.

Database diff, tag
Rollback
Preconditions
Dobre praktyki
Integracja z Maven i Eclipse
Inne…

Piotr Pelczar
me@athlan.pl
Wersjonowanie baz danych
podczas developmentu

Liquibase
Piotr Pelczar
me@athlan.pl

Liquibase - database structure versioning