# Reset PostgreSQL / Timescale (Docker) a obnova z dumpu Přesný postup pro **smazání dat databáze** (volume) a **nový import** `pg_dump -Fc` na serveru typu `/opt/ems-deploy`. Po resetu zmizí veškerá data v DB EMS. **Související skripty v repu:** `scripts/import_ems_db.sh`, `scripts/export_ems_db.sh`. Obecný kontext self-hosted deploye: [deployment-self-hosted.md](deployment-self-hosted.md). --- ## 0. Před začátkem - Máš zálohu `.dump` (custom format), ideálně z `scripts/export_ems_db.sh` nebo ekvivalentního `pg_dump -Fc`. - **`DB_USER` / `DB_PASSWORD` v `.env` na cíli** odpovídají tomu, co očekává init kontejneru `db` (po smazání volume se DB vytvoří znovu se stejnými údaji z `.env`). - Timescale: image `timescale/timescaledb:latest-pg16` se v čase mění. Záloha ze **staršího** Timescale na **novější** imagi vyžaduje po restore `ALTER EXTENSION timescaledb UPDATE` — to už dělá `import_ems_db.sh`. Při problémech zvaž **pin** imagi (např. `:2.25.2-pg16`) stejně jako u zdroje dumpu. - **`pg_restore` nikdy s `-j`** (paralelní restore) u Timescale. --- ## 1. (Volitelně) Export z vývojového stroje Z kořene repa, kde běží lokální `docker compose` a `.env` s `DB_USER` / `DB_PASSWORD`: ```bash cd /cesta/k/ems-cursor ./scripts/export_ems_db.sh ~/ems_zaloha_$(date +%Y%m%d_%H%M%S).dump ``` Přenos na server (příklad): ```bash scp ~/ems_zaloha_*.dump root@server:/tmp/ems.dump ``` --- ## 2. Na serveru: zastavit služby, které píší do DB Aby při mazání volume a restore nebyl konflikt: ```bash cd /opt/ems-deploy docker compose --env-file .env stop backend postgrest frontend ``` (`db` nech může běžet do kroku 4, nebo všechno zastavit — viz krok 3.) --- ## 3. Zastavit stack a smazat datový volume Postgresu ```bash cd /opt/ems-deploy docker compose --env-file .env down ``` **Jméno volume** závisí na názvu Compose projektu (složka nebo `COMPOSE_PROJECT_NAME`). Zjisti ho: ```bash docker volume ls | grep -E 'db_data|ems' ``` Typicky u deploye z `/opt/ems-deploy` uvidíš něco jako `ems-deploy_db_data` (prefix `{project}_db_data` k klíči `db_data:` z compose). **Smaž volume** (doplň přesný název z výpisu): ```bash docker volume rm ems-deploy_db_data ``` Tím zmizí **celý** obsah dat Postgresu v tom projektu. Ostatní Docker volume (pokud nějaké máš) se nedotknou. --- ## 4. Naběhnout jen databázi ```bash cd /opt/ems-deploy docker compose --env-file .env up -d db docker compose --env-file .env ps ``` Počkej, až je služba `db` **healthy** (`pg_isready` v healthchecku). Init image vytvoří prázdnou databázi **`ems`** a uživatele z `POSTGRES_USER` / `POSTGRES_PASSWORD`. --- ## 5. Import dumpu (Timescale hooks + restore) Dump musí být na serveru, např. `/tmp/ems.dump`. ```bash cd /opt/ems-deploy bash app/scripts/import_ems_db.sh /tmp/ems.dump ``` Skript v kontejneru `db` postupně: 1. `CREATE EXTENSION IF NOT EXISTS timescaledb` 2. `SELECT timescaledb_pre_restore();` 3. `pg_restore` **bez** `-j` (`--clean --if-exists --no-owner --no-acl`) 4. `ALTER EXTENSION timescaledb UPDATE;` (srovnání katalogu se verzí v imagi) 5. `SELECT timescaledb_post_restore();` Výjimky: `EMS_SKIP_TIMESCALE_RESTORE_HOOKS=1` v prostředí přeskočí body 2 a 5 (jen výjimečně). **Časté jevy:** - `pg_restore: warning: errors ignored` — často kvůli FK na hypertable (`ALTER TABLE ONLY`). Po importu **vždy** Flyway (migrace **V034** doplní chybějící FK). - Selhání **catalog version mismatch** — typicky vyřeší `ALTER EXTENSION` ve skriptu; jinak pin Timescale imagi nebo nový dump po upgrade zdroje. --- ## 6. Flyway migrace Doplní schéma oproti dumpu (včetně oprav PK/chunků/FK z V032–V034 podle verze repa): ```bash cd /opt/ems-deploy docker compose --env-file .env run --rm flyway migrate ``` --- ## 7. Celý stack ```bash cd /opt/ems-deploy docker compose --env-file .env up -d ``` Nebo jednorázový deploy z aplikace: ```bash /opt/ems-deploy/deploy.sh ``` (`deploy.sh` dělá git sync, `flyway migrate`, `build`, `up -d` — pokud už jsi Flyway spustil v kroku 6, znovu obvykle jen doplní repeatable migrace.) --- ## 8. Rychlá kontrola ```bash docker compose -f /opt/ems-deploy/docker-compose.yml --env-file /opt/ems-deploy/.env ps ``` Volitelně SQL (z hosta přes `docker compose exec`): ```bash docker compose --env-file .env exec -T -e PGPASSWORD="$DB_PASSWORD" db \ psql -U "$DB_USER" -d ems -c "SELECT count(*) FROM ems.site;" ``` --- ## 9. Slabší varianta bez mazání volume Pokud nechceš mazat celý volume, lze zkusit přepnout databázi uvnitř (méně typické u Timescale; u poškozeného katalogu chunků je **spolehlivější smazat volume**): ```bash docker compose --env-file .env exec -T -e PGPASSWORD="$DB_PASSWORD" db \ psql -U "$DB_USER" -d postgres -c "DROP DATABASE IF EXISTS ems WITH (FORCE);" docker compose --env-file .env exec -T -e PGPASSWORD="$DB_PASSWORD" db \ psql -U "$DB_USER" -d postgres -c "CREATE DATABASE ems OWNER \"${DB_USER}\";" ``` Pak znovu **`import_ems_db.sh`** a **Flyway**. --- ## 10. Robustnější strategie (odkaz) Plný „schema odděleně od dat“ a obnova hypertable přes `create_hypertable` popisuje **Tiger Data / Timescale** v dokumentaci k backupu a restore. Tento repozitář používá praktický jednokrokový `-Fc` restore přes `import_ems_db.sh`; u opakovaných problémů zvaž jejich oficiální postup (pre-data dump bez `_timescaledb*`, data zvlášť). --- ## 11. Shrnutí příkazů (kostra) ```bash # server cd /opt/ems-deploy docker compose --env-file .env stop backend postgrest frontend docker compose --env-file .env down docker volume rm # z docker volume ls docker compose --env-file .env up -d db # počkat healthy bash app/scripts/import_ems_db.sh /tmp/ems.dump docker compose --env-file .env run --rm flyway migrate docker compose --env-file .env up -d ```