Database Migrations — Verziovanie databázových schém
Databázové migrácie sú kontrolované, verziované zmeny databázovej schémy. Rovnako ako verzionujeme kód v Gite, migrácie umožňujú verziovať štruktúru databázy — tabuľky, indexy, constrainty, stored procedúry.
Prečo migrácie?
Bez migrácií sa tímy spoliehajú na manuálne SQL skripty, zdieľané databázy a "prosím, spusti toto na produkcii". Výsledok:
- Nekonzistentné prostredia — dev, staging a production majú rôzne schémy
- Strach z deploymentu — nikto nevie, aké zmeny sú potrebné
- Nereprodukovateľnosť — nový vývojár nedokáže vytvoriť funkčnú databázu
- Rollback nemožný — pri probléme nie je cesta späť
Migračné nástroje riešia všetky tieto problémy systematicky.
Princípy database migrations
1. Migrácie sú sekvenčné
Každá migrácia má poradové číslo alebo timestamp. Spúšťajú sa vždy v poradí:
V001__create_users_table.sql
V002__add_email_to_users.sql
V003__create_orders_table.sql
V004__add_index_on_email.sql
2. Migrácie sú immutable
Raz spustená migrácia sa nikdy nemení. Ak potrebujete opravu, vytvoríte novú migráciu. Nástroje kontrolujú checksum a odmietnu spustiť zmenenú migráciu.
3. Migrácie sú v Gite
Migračné súbory žijú v repozitári spolu s kódom. Code review zahŕňa aj database zmeny.
Flyway
Flyway je open-source migračný nástroj od Red Gate. Je jednoduchý, spoľahlivý a širokou podporou databáz.
Štruktúra projektu
src/main/resources/db/migration/
├── V1__create_users.sql
├── V2__create_products.sql
├── V3__add_user_roles.sql
├── R__refresh_views.sql # Repeatable migration
└── U2__undo_products.sql # Undo migration
Konvencie pomenovania
V{version}__{description}.sql— verziované migrácieR__{description}.sql— opakovateľné migrácie (views, functions)U{version}__{description}.sql— undo migrácie
Flyway CLI
# Migrácia na najnovšiu verziu
flyway migrate
# Stav migrácií
flyway info
# Validácia migrácií
flyway validate
# Vyčistenie (len dev!)
flyway clean
# Baseline existujúcej DB
flyway baseline -baselineVersion=1
# Oprava metadata tabuľky
flyway repair
Flyway v Docker
docker run --rm \
-v $(pwd)/sql:/flyway/sql \
flyway/flyway \
-url=jdbc:postgresql://db:5432/myapp \
-user=postgres \
-password=secret \
migrate
Flyway v CI/CD pipeline
# GitHub Actions
- name: Run Flyway migrations
uses: flyway/flyway-action@v1
with:
url: jdbc:postgresql://${{ secrets.DB_HOST }}:5432/myapp
user: ${{ secrets.DB_USER }}
password: ${{ secrets.DB_PASSWORD }}
command: migrate
Liquibase
Liquibase je pokročilejší migračný nástroj s podporou XML, YAML, JSON a SQL formátov. Ponúka viac flexibility ako Flyway.
Changelog príklad (YAML)
databaseChangeLog:
- changeSet:
id: 1
author: peter
changes:
- createTable:
tableName: users
columns:
- column:
name: id
type: bigint
autoIncrement: true
constraints:
primaryKey: true
- column:
name: email
type: varchar(255)
constraints:
unique: true
nullable: false
- column:
name: created_at
type: timestamp
defaultValueComputed: CURRENT_TIMESTAMP
- changeSet:
id: 2
author: peter
changes:
- addColumn:
tableName: users
columns:
- column:
name: role
type: varchar(50)
defaultValue: "user"
rollback:
- dropColumn:
tableName: users
columnName: role
Liquibase CLI
# Spustenie migrácií
liquibase update
# Stav
liquibase status
# Rollback posledného changeset-u
liquibase rollbackCount 1
# Rollback na tag
liquibase rollback v1.0
# Generovanie SQL bez spustenia
liquibase updateSQL
# Diff medzi dvoma databázami
liquibase diff \
--referenceUrl=jdbc:postgresql://localhost/staging \
--url=jdbc:postgresql://localhost/production
Zero-Downtime migrácie
Najväčšia výzva — ako zmeniť schému bez výpadku? Kľúčový princíp: backward compatibility.
Bezpečné operácie
| Operácia | Bezpečná? | Poznámka |
|---|---|---|
| Pridať stĺpec (nullable) | ✅ | Starý kód ho ignoruje |
| Pridať tabuľku | ✅ | Neovplyvní existujúci kód |
| Pridať index (CONCURRENTLY) | ✅ | Neblokuje zápisy |
| Odstrániť stĺpec | ❌ | Starý kód ho môže čítať |
| Premenovať stĺpec | ❌ | Starý kód zlyhá |
| Zmeniť typ stĺpca | ❌ | Môže zlyhať konverzia |
Expand-Contract pattern
Pre nebezpečné zmeny používame expand-contract (alebo parallel change) pattern:
Príklad: Premenovanie stĺpca name → full_name
Fáza 1 — Expand (migrácia):
-- V5: Pridaj nový stĺpec
ALTER TABLE users ADD COLUMN full_name VARCHAR(255);
-- Skopíruj dáta
UPDATE users SET full_name = name WHERE full_name IS NULL;
-- Trigger pre synchronizáciu počas deployu
CREATE OR REPLACE FUNCTION sync_name()
RETURNS TRIGGER AS $$
BEGIN
NEW.full_name = NEW.name;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER sync_name_trigger
BEFORE INSERT OR UPDATE ON users
FOR EACH ROW EXECUTE FUNCTION sync_name();
Fáza 2 — Migrate code: Aplikácia začne používať full_name namiesto name.
Fáza 3 — Contract (migrácia):
-- V7: Odstráň starý stĺpec (až keď všetky inštancie používajú full_name)
DROP TRIGGER sync_name_trigger ON users;
DROP FUNCTION sync_name();
ALTER TABLE users DROP COLUMN name;
Online Schema Changes (veľké tabuľky)
Pre tabuľky s miliónmi riadkov štandardný ALTER TABLE môže trvať hodiny a blokovať:
# gh-ost (GitHub Online Schema Change)
gh-ost \
--host=db.example.com \
--database=myapp \
--table=users \
--alter="ADD COLUMN phone VARCHAR(20)" \
--execute
# pt-online-schema-change (Percona)
pt-online-schema-change \
--alter "ADD COLUMN phone VARCHAR(20)" \
D=myapp,t=users \
--execute
Tieto nástroje vytvárajú shadow tabuľku, postupne kopírujú dáta a na konci robia atomic swap.
Schema versioning v praxi
Migračná tabuľka
Flyway aj Liquibase si udržiavajú tracking tabuľku:
-- Flyway: flyway_schema_history
SELECT version, description, success, installed_on
FROM flyway_schema_history
ORDER BY installed_rank;
-- version | description | success | installed_on
-- 1 | create users | true | 2026-03-01 10:00
-- 2 | add orders | true | 2026-03-05 14:30
-- 3 | add user roles | true | 2026-03-14 09:00
Seed data vs migrácie
- Migrácie — schéma zmeny (DDL)
- Seed data — referenčné dáta (krajiny, roly, kategórie)
- Test fixtures — testovacie dáta (len pre dev/test)
-- R__seed_roles.sql (repeatable migration)
INSERT INTO roles (name) VALUES ('admin')
ON CONFLICT (name) DO NOTHING;
INSERT INTO roles (name) VALUES ('user')
ON CONFLICT (name) DO NOTHING;
Porovnanie Flyway vs Liquibase
| Aspekt | Flyway | Liquibase |
|---|---|---|
| Formát | SQL (+ Java) | XML, YAML, JSON, SQL |
| Rollback | Platené (Teams) | Zadarmo |
| Diff | Nie | Áno |
| Zložitosť | Jednoduchý | Komplexnejší |
| DB support | 20+ databáz | 50+ databáz |
| Changelog | File-based | Centralizovaný |
| Pre tímy | Malé-stredné | Stredné-veľké |
Best Practices
- Jedna migrácia = jedna zmena — atomické, zrozumiteľné zmeny
- Nikdy nemodifikujte existujúce migrácie — vždy nová migrácia
- Testujte migrácie v CI — spustiť na čistej DB pred merge-om
- Backward compatible zmeny — expand-contract pattern
- Review SQL v PR — migrácie sú rovnako dôležité ako kód
- Záloha pred produkčnou migráciou — vždy
- Monitorujte čas migrácie — dlhé migrácie = potenciálny downtime
Databázové migrácie sú neoddeliteľnou súčasťou moderného vývoja. S nástrojmi ako Flyway alebo Liquibase a praktikami ako expand-contract pattern dokážete bezpečne meniť schémy aj na produkčných databázach s miliónmi záznamov.