🟡 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 namefull_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.