Obchodní logika v databázi pomocí SchemaKeeper

Cílem tohoto článku je na příkladu knihovny schema-keeper ukázat nástroje, které výrazně usnadňují proces vývoje databází v rámci PHP projektů využívajících databázový systém PostgreSQL.

Informace v tomto článku budou zejména užitečné pro vývojáře, kteří chtějí maximálně využít možnosti PostgreSQL, ale setkávají se s problémy při údržbě obchodní logiky uložené v databázi.

Článek nebude popisovat výhody ani nevýhody ukládání obchodní logiky do databáze. Předpokládá se, že výběr již byl učiněn čtenářem.

Budou probírány následující otázky:

  1. Jak uchovávat dump struktury databáze v systému řízení verzí (dále jen VCS)
  2. Jak sledovat změny ve struktuře databáze po uložení dumpu
  3. Jak přenášet změny ve struktuře databáze na jiná prostředí bez konfliktů a obrovských migračních souborů
  4. Jak nastavit proces paralelní práce na projektu pro více vývojářů
  5. Jak bezpečně nasazovat větší množství změn ve struktuře databáze na produkční prostředí

    SchemaKeeper je zaměřen na práci s uloženými procedurami napsanými v jazyce PL/pgSQL. Testování s jinými jazyky nebylo provedeno, a tudíž použití nemusí být tak efektivní, nebo možné.

Jak uchovávat dump struktury databáze v VCS

Knihovna schema-keeper poskytuje funkci saveDump, která ukládá strukturu všech objektů z databáze jako jednotlivé textové soubory. Vytváří se výstupní adresář, který obsahuje strukturu databáze rozdělenou do skupinových souborů, které lze snadno přidat do VCS.

Podívejme se na transformaci objektů z databáze na soubory na několika příkladech:

Typ objektu
Schéma
Název
Relativní cesta k souboru

Tabulka
public
accounts
./public/tables/accounts.txt

Uložená procedura
public
auth(hash bigint)
./public/functions/auth(int8).sql

Zobrazení
booking
tariffs
./booking/views/tariffs.txt

Obsahem souborů je textová reprezentace struktury konkrétního objektu databáze. Například pro uložené procedury bude obsahem souboru úplná definice uložené procedury, začínající blokem CREATE OR REPLACE FUNCTION.

Jak je vidět z výše uvedené tabulky, cesta k souboru obsahuje informace o typu, schématu a názvu objektu. Tento přístup usnadňuje navigaci v dumpu a přezkum změn v databázi.

Rozšíření .sql Pro soubory s kódem uložených procedur je vybrána možnost, aby IDE automaticky nabízely nástroje pro interakci s DB při otevření souboru.

Jak sledovat změny ve struktuře databáze po uložení dumpu

Uložením dumpu aktuální struktury DB do VCS získáváme možnost zkontrolovat, zda došlo ke změnám ve struktuře databáze po vytvoření dumpu. V knihovně schema-keeper je předpřipravená funkce pro identifikaci změn struktury DB verifyDump, která bez vedlejších účinků vrací informace o rozdílech.

Alternativní způsob kontroly – znovu vyvolat funkci saveDump, uvést stejný adresář a zkontrolovat v VCS přítomnost změn. Vzhledem k tomu, že všechny objekty z DB jsou uloženy v samostatných souborech, VCS zobrazí pouze změněné objekty.
Hlavní nevýhodou tohoto způsobu je potřeba přepsat soubory, abychom viděli změny.

Jak přenášet změny ve struktuře databáze na jiná prostředí bez konfliktů a obrovských migračních souborů

Díky funkci deployDump může být zdrojový kód uložených procedur upravován stejně jako obyčejný zdrojový kód aplikace. Můžeme přidávat/odstraňovat nové řádky v kódu uložených procedur a okamžitě odesílat změny do systému kontroly verzí, nebo vytvářet/odstraňovat uložené procedury vytvářením/odstraňováním odpovídajících souborů v adresáři s dumpem.

Například pro vytvoření nové uložené procedury ve schématu public stačí vytvořit nový soubor s příponou .sql v adresáři public/functions, vložit do něj zdrojový kód uložené procedury včetně bloku CREATE OR REPLACE FUNCTION, a poté vyvolat funkci deployDump. Podobně probíhá změna a odstranění uložené procedury. Takto kód zároveň vstupuje do VCS i do databáze.

Pokud se ve zdrojovém kódu nějaké uložené procedury objeví chyba nebo nesoulad mezi názvy souboru a uloženou procedurou, pak deployDump se neprovede a zobrazí text chyby. Neshoda uložených procedur mezi dumpem a aktuální DB je nemožná při použití deployDump.

Při vytváření nové uložené procedury není nutné ručně zadávat správný název souboru. Stačí, aby měl soubor příponu .sql. Po vyvolání deployDump bude text chyby obsahovat správný název, který lze použít pro přejmenování souboru.

deployDump umožňuje měnit parametry funkce nebo návratový typ bez dalších kroků, zatímco při klasickém přístupu by bylo nutné
nejprve provést DROP FUNCTION, a teprve poté CREATE OR REPLACE FUNCTION.

Bohužel existují situace, kdy deployDump není možné automaticky aplikovat změny. Například pokud je odstraněna trigger funkce, která je používána alespoň jedním triggem. Takové situace se řeší ručně pomocí migračních souborů.

Pokud za přenos změn ve stored procedures odpovídá sám schema-keeper, pak pro přenos ostatních změn ve struktuře je nutné použít migrační soubory. Například dobrou knihovnou pro práci s migracemi je doctrine/migrations.

Migrace by měly být aplikovány před spuštěním deployDump. To umožňuje provést všechny změny ve struktuře a vyřešit problémové situace, aby se změny ve stored procedures později přenesly bez problémů.

Podrobněji se práce s migracemi popíše v následujících sekcích.

Jak nastavit proces paralelní práce na projektu pro více vývojářů

Je nutné vytvořit skript pro kompletní inicializaci databáze, který bude spuštěn vývojářem na jeho pracovním stroji, aby se struktura lokální databáze uvedla do souladu se zálohou uloženou ve VCS. Nejjednodušší je rozdělit inicializaci lokální databáze do třech kroků:

  1. Import souboru s základní strukturou, který se bude jmenovat například base.sql
  2. Aplikace migrací
  3. Zavolání deployDump

base.sql — to je výchozí bod, na který se aplikují migrace a provádí se deployDump, to znamená base.sql + migrace + deployDump = aktuální struktura databáze. Takový soubor lze vytvořit pomocí utilit. pg_dumpPoužívá se base.sql výhradně při inicializaci databáze od nuly.

Nazveme skript pro kompletní inicializaci databáze refresh.sh. Pracovní proces může vypadat následovně:

  1. Vývojář spustí ve svém prostředí refresh.sh a získá aktuální strukturu databáze.
  2. Vývojář začne pracovat na zadaném úkolu, modifikuje lokální databázi podle potřeb nové funkce (ALTER TABLE ... ADD COLUMN atd.)
  3. Po dokončení úkolu vývojář zavolá funkci saveDump, aby zapsal do VCS změny provedené v databázi.
  4. Vývojář znovu spustí refresh.sh, poté verifyDump, který nyní zobrazuje seznam změn k zahrnutí do migrace.
  5. Vývojář převede všechny změny struktury do migračního souboru, spustí znovu refresh.sh a verifyDump, a pokud je migrace správně vytvořena, verifyDump ukáže absenci rozdílů mezi lokální databází a uloženou zálohou.

Popisovaný proces je kompatibilní s principy gitflow. Každá větev v VCS bude obsahovat svou vlastní verzi dumpu, a při sloučení větví dojde ke sloučení dumpů. Většinou není potřeba po sloučení provádět žádné další akce, ale pokud došlo ke změnám v různých větvích, například ve stejné tabulce, může nastat konflikt.

Zvažme konfliktní situaci na příkladu: existuje větev develop, od které se odvojují dvě větve: feature1 a feature2, které nemají konflikty s develop, ale mají konflikty mezi sebou. Úkolem je provést sloučení obou větví do develop. V takovém případě se doporučuje nejprve provést sloučení jedné z větví do develop, a poté sloučení develop do zbývající větve, přičemž se vyřeší konflikty v této zbývající větvi, a nakonec provést sloučení poslední větve do develop. Během fáze řešení konfliktů bude možná třeba upravit migrační soubor v poslední větvi, aby odpovídal konečnému dumpu zahrnujícímu výsledky sloučení.

Jak bezpečně nasazovat větší množství změn ve struktuře databáze na produkční prostředí

Díky tomu, že VCS obsahuje dump aktuální struktury DB, je možné zkontrolovat produkční databázi na přesné dodržení požadované struktury. To zaručuje, že se do produkční databáze úspěšně přenesly všechny změny, které zamýšleli vývojáři.

Protože DDL v PostgreSQL je transakční, doporučuje se dodržovat následující pořadí nasazení, aby bylo možné v případě nepředvídané chyby provést „bezbolestně“ ROLLBACK:

  1. Zahájit transakci
  2. V transakci provést všechny migrace
  3. Ve stejné transakci provést deployDump
  4. Neukončující transakci provést verifyDump. Pokud nejsou žádné chyby, provést COMMIT. Pokud jsou chyby, provést ROLLBACK

Tyto kroky se poměrně snadno integrují do stávajících přístupů k nasazení aplikací, včetně zero-downtime.

Závěr

Díky výše uvedeným metodám je možné vytěžit maximum výkonu z projektů „PHP + PostgreSQL“, a to na úkor relativně malého množství pohodlí při vývoji ve srovnání s implementací celé obchodní logiky v hlavním kódu aplikace. Navíc zpracování dat v PL/pgSQL často vypadá transparentněji a vyžaduje méně kódu než stejná funkcionalita napsaná v PHP.

Zdroj: habr.com

Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery 🔥 Koupit spolehlivý hosting pro webové stránky s ochranou proti DDoS, VPS VDS servery | ProHoster