Cílem tohoto článku je na příkladu knihovny 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:
- Jak uchovávat dump struktury databáze v systému řízení verzí (dále jen VCS)
- Jak sledovat změny ve struktuře databáze po uložení dumpu
- Jak přenášet změny ve struktuře databáze na jiná prostředí bez konfliktů a obrovských migračních souborů
- Jak nastavit proces paralelní práce na projektu pro více vývojářů
- 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 . 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 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í
.sqlPro 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ě 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ídeployDumpbude 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 , 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 .
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ů:
- Import souboru s základní strukturou, který se bude jmenovat například
base.sql - Aplikace migrací
- Zavolání
deployDump
base.sql— to je výchozí bod, na který se aplikují migrace a provádí sedeployDump, to znamenábase.sql + migrace + deployDump = aktuální struktura databáze. Takový soubor lze vytvořit pomocí utilit.pg_dumpPoužívá sebase.sqlvýhradně při inicializaci databáze od nuly.
Nazveme skript pro kompletní inicializaci databáze refresh.sh. Pracovní proces může vypadat následovně:
- Vývojář spustí ve svém prostředí
refresh.sha získá aktuální strukturu databáze. - Vývojář začne pracovat na zadaném úkolu, modifikuje lokální databázi podle potřeb nové funkce (
ALTER TABLE ... ADD COLUMNatd.) - Po dokončení úkolu vývojář zavolá funkci
saveDump, aby zapsal do VCS změny provedené v databázi. - Vývojář znovu spustí
refresh.sh, potéverifyDump, který nyní zobrazuje seznam změn k zahrnutí do migrace. - Vývojář převede všechny změny struktury do migračního souboru, spustí znovu
refresh.shaverifyDump, a pokud je migrace správně vytvořena,verifyDumpukáž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 v PostgreSQL je , 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:
- Zahájit transakci
- V transakci provést všechny migrace
- Ve stejné transakci provést
deployDump - Neukončující transakci provést
verifyDump. Pokud nejsou žádné chyby, provéstCOMMIT. Pokud jsou chyby, provéstROLLBACK
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 často vypadá transparentněji a vyžaduje méně kódu než stejná funkcionalita napsaná v PHP.
Zdroj: habr.com
