🟡 Intermediate

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ácie
  • R__{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

  1. Jedna migrácia = jedna zmena — atomické, zrozumiteľné zmeny
  2. Nikdy nemodifikujte existujúce migrácie — vždy nová migrácia
  3. Testujte migrácie v CI — spustiť na čistej DB pred merge-om
  4. Backward compatible zmeny — expand-contract pattern
  5. Review SQL v PR — migrácie sú rovnako dôležité ako kód
  6. Záloha pred produkčnou migráciou — vždy
  7. 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.