{"id":31385,"date":"2019-10-31T21:40:58","date_gmt":"2019-10-31T18:40:58","guid":{"rendered":"https:\/\/prohoster.info\/blog\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper\/"},"modified":"2019-10-31T21:40:58","modified_gmt":"2019-10-31T18:40:58","slug":"biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper","status":"publish","type":"post","link":"https:\/\/prohoster.info\/cs\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper","title":{"rendered":"Obchodn\u00ed logika v datab\u00e1zi pomoc\u00ed SchemaKeeper","gt_translate_keys":[{"key":"rendered","format":"text"}]},"content":{"rendered":"<p>C\u00edlem tohoto \u010dl\u00e1nku je na p\u0159\u00edkladu knihovny <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex> uk\u00e1zat n\u00e1stroje, kter\u00e9 v\u00fdrazn\u011b usnad\u0148uj\u00ed proces v\u00fdvoje datab\u00e1z\u00ed v r\u00e1mci PHP projekt\u016f vyu\u017e\u00edvaj\u00edc\u00edch datab\u00e1zov\u00fd syst\u00e9m PostgreSQL.<\/p>\n<p><\/p>\n<p>Informace v tomto \u010dl\u00e1nku budou zejm\u00e9na u\u017eite\u010dn\u00e9 pro v\u00fdvoj\u00e1\u0159e, kte\u0159\u00ed cht\u011bj\u00ed maxim\u00e1ln\u011b vyu\u017e\u00edt mo\u017enosti PostgreSQL, ale setk\u00e1vaj\u00ed se s probl\u00e9my p\u0159i \u00fadr\u017eb\u011b obchodn\u00ed logiky ulo\u017een\u00e9 v datab\u00e1zi. <\/p>\n<p><\/p>\n<p>\u010cl\u00e1nek nebude popisovat v\u00fdhody ani nev\u00fdhody ukl\u00e1d\u00e1n\u00ed obchodn\u00ed logiky do datab\u00e1ze. P\u0159edpokl\u00e1d\u00e1 se, \u017ee v\u00fdb\u011br ji\u017e byl u\u010din\u011bn \u010dten\u00e1\u0159em.<\/p>\n<p><\/p>\n<p>Budou prob\u00edr\u00e1ny n\u00e1sleduj\u00edc\u00ed ot\u00e1zky:<\/p>\n<p><\/p>\n<ol>\n<li>Jak uchov\u00e1vat dump struktury datab\u00e1ze v syst\u00e9mu \u0159\u00edzen\u00ed verz\u00ed (d\u00e1le jen VCS)<\/li>\n<li>Jak sledovat zm\u011bny ve struktu\u0159e datab\u00e1ze po ulo\u017een\u00ed dumpu<\/li>\n<li>Jak p\u0159en\u00e1\u0161et zm\u011bny ve struktu\u0159e datab\u00e1ze na jin\u00e1 prost\u0159ed\u00ed bez konflikt\u016f a obrovsk\u00fdch migra\u010dn\u00edch soubor\u016f<\/li>\n<li>Jak nastavit proces paraleln\u00ed pr\u00e1ce na projektu pro v\u00edce v\u00fdvoj\u00e1\u0159\u016f<\/li>\n<li>Jak bezpe\u010dn\u011b nasazovat v\u011bt\u0161\u00ed mno\u017estv\u00ed zm\u011bn ve struktu\u0159e datab\u00e1ze na produk\u010dn\u00ed prost\u0159ed\u00ed<noindex><a rel=\"nofollow\" name=\"habracut\"><\/a><\/noindex><br \/>\n<blockquote><p><strong>SchemaKeeper<\/strong> je zam\u011b\u0159en na pr\u00e1ci s ulo\u017een\u00fdmi procedurami napsan\u00fdmi v jazyce <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/plpgsql.html\">PL\/pgSQL<\/a><\/noindex>. Testov\u00e1n\u00ed s jin\u00fdmi jazyky nebylo provedeno, a tud\u00ed\u017e pou\u017eit\u00ed nemus\u00ed b\u00fdt tak efektivn\u00ed, nebo mo\u017en\u00e9.\n<\/p><\/blockquote>\n<\/li>\n<\/ol>\n<p><\/p>\n<h2 id=\"v-kakom-vide-hranit-damp-struktury-bd-v-vcs\">Jak uchov\u00e1vat dump struktury datab\u00e1ze v VCS<\/h2>\n<p><\/p>\n<p>Knihovna <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex> poskytuje funkci <code>saveDump<\/code>, kter\u00e1 ukl\u00e1d\u00e1 strukturu v\u0161ech objekt\u016f z datab\u00e1ze jako jednotliv\u00e9 textov\u00e9 soubory. Vytv\u00e1\u0159\u00ed se v\u00fdstupn\u00ed adres\u00e1\u0159, kter\u00fd obsahuje strukturu datab\u00e1ze rozd\u011blenou do skupinov\u00fdch soubor\u016f, kter\u00e9 lze snadno p\u0159idat do VCS.<\/p>\n<p><\/p>\n<p>Pod\u00edvejme se na transformaci objekt\u016f z datab\u00e1ze na soubory na n\u011bkolika p\u0159\u00edkladech:<\/p>\n<p><\/p>\n<p>Typ objektu<br \/>\nSch\u00e9ma<br \/>\nN\u00e1zev<br \/>\nRelativn\u00ed cesta k souboru<\/p>\n<p>Tabulka<br \/>\npublic<br \/>\naccounts<br \/>\n<code>.\/public\/tables\/accounts.txt<\/code><\/p>\n<p>Ulo\u017een\u00e1 procedura<br \/>\npublic<br \/>\nauth(hash bigint)<br \/>\n<code>.\/public\/functions\/auth(int8).sql<\/code><\/p>\n<p>Zobrazen\u00ed<br \/>\nbooking<br \/>\ntariffs<br \/>\n<code>.\/booking\/views\/tariffs.txt<\/code><\/p>\n<p><\/p>\n<p>Obsahem soubor\u016f je textov\u00e1 reprezentace struktury konkr\u00e9tn\u00edho objektu datab\u00e1ze. Nap\u0159\u00edklad pro ulo\u017een\u00e9 procedury bude obsahem souboru \u00fapln\u00e1 definice ulo\u017een\u00e9 procedury, za\u010d\u00ednaj\u00edc\u00ed blokem <code>CREATE OR REPLACE FUNCTION<\/code>.<\/p>\n<p><\/p>\n<p>Jak je vid\u011bt z v\u00fd\u0161e uveden\u00e9 tabulky, cesta k souboru obsahuje informace o typu, sch\u00e9matu a n\u00e1zvu objektu. Tento p\u0159\u00edstup usnad\u0148uje navigaci v dumpu a p\u0159ezkum zm\u011bn v datab\u00e1zi.<\/p>\n<p><\/p>\n<blockquote><p>Roz\u0161\u00ed\u0159en\u00ed <code>.sql<\/code> Pro soubory s k\u00f3dem ulo\u017een\u00fdch procedur je vybr\u00e1na mo\u017enost, aby IDE automaticky nab\u00edzely n\u00e1stroje pro interakci s DB p\u0159i otev\u0159en\u00ed souboru.<\/p><\/blockquote>\n<p><\/p>\n<h2 id=\"kak-otslezhivat-izmeneniya-v-strukture-bd-posle-sohraneniya-dampa\">Jak sledovat zm\u011bny ve struktu\u0159e datab\u00e1ze po ulo\u017een\u00ed dumpu<\/h2>\n<p><\/p>\n<p>Ulo\u017een\u00edm dumpu aktu\u00e1ln\u00ed struktury DB do VCS z\u00edsk\u00e1v\u00e1me mo\u017enost zkontrolovat, zda do\u0161lo ke zm\u011bn\u00e1m ve struktu\u0159e datab\u00e1ze po vytvo\u0159en\u00ed dumpu. V knihovn\u011b <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex> je p\u0159edp\u0159ipraven\u00e1 funkce pro identifikaci zm\u011bn struktury DB <code>verifyDump<\/code>, kter\u00e1 bez vedlej\u0161\u00edch \u00fa\u010dink\u016f vrac\u00ed informace o rozd\u00edlech. <\/p>\n<p><\/p>\n<p>Alternativn\u00ed zp\u016fsob kontroly \u2013 znovu vyvolat funkci <code>saveDump<\/code>, uv\u00e9st stejn\u00fd adres\u00e1\u0159 a zkontrolovat v VCS p\u0159\u00edtomnost zm\u011bn. Vzhledem k tomu, \u017ee v\u0161echny objekty z DB jsou ulo\u017eeny v samostatn\u00fdch souborech, VCS zobraz\u00ed pouze zm\u011bn\u011bn\u00e9 objekty.<br \/>\nHlavn\u00ed nev\u00fdhodou tohoto zp\u016fsobu je pot\u0159eba p\u0159epsat soubory, abychom vid\u011bli zm\u011bny.<\/p>\n<p><\/p>\n<h2 id=\"kak-perenosit-izmeneniya-v-strukture-bd-na-drugie-okruzheniya-bez-konfliktov-i-gigantskih-faylov-migraciy\">Jak p\u0159en\u00e1\u0161et zm\u011bny ve struktu\u0159e datab\u00e1ze na jin\u00e1 prost\u0159ed\u00ed bez konflikt\u016f a obrovsk\u00fdch migra\u010dn\u00edch soubor\u016f<\/h2>\n<p><\/p>\n<p>D\u00edky funkci <code>deployDump<\/code> m\u016f\u017ee b\u00fdt zdrojov\u00fd k\u00f3d ulo\u017een\u00fdch procedur upravov\u00e1n stejn\u011b jako oby\u010dejn\u00fd zdrojov\u00fd k\u00f3d aplikace. M\u016f\u017eeme p\u0159id\u00e1vat\/odstra\u0148ovat nov\u00e9 \u0159\u00e1dky v k\u00f3du ulo\u017een\u00fdch procedur a okam\u017eit\u011b odes\u00edlat zm\u011bny do syst\u00e9mu kontroly verz\u00ed, nebo vytv\u00e1\u0159et\/odstra\u0148ovat ulo\u017een\u00e9 procedury vytv\u00e1\u0159en\u00edm\/odstra\u0148ov\u00e1n\u00edm odpov\u00eddaj\u00edc\u00edch soubor\u016f v adres\u00e1\u0159i s dumpem. <\/p>\n<p><\/p>\n<p>Nap\u0159\u00edklad pro vytvo\u0159en\u00ed nov\u00e9 ulo\u017een\u00e9 procedury ve sch\u00e9matu <code>public<\/code> sta\u010d\u00ed vytvo\u0159it nov\u00fd soubor s p\u0159\u00edponou <code>.sql<\/code> v adres\u00e1\u0159i <code>public\/functions<\/code>, vlo\u017eit do n\u011bj zdrojov\u00fd k\u00f3d ulo\u017een\u00e9 procedury v\u010detn\u011b bloku <code>CREATE OR REPLACE FUNCTION<\/code>, a pot\u00e9 vyvolat funkci <code>deployDump<\/code>. Podobn\u011b prob\u00edh\u00e1 zm\u011bna a odstran\u011bn\u00ed ulo\u017een\u00e9 procedury. Takto k\u00f3d z\u00e1rove\u0148 vstupuje do VCS i do datab\u00e1ze. <\/p>\n<p><\/p>\n<p>Pokud se ve zdrojov\u00e9m k\u00f3du n\u011bjak\u00e9 ulo\u017een\u00e9 procedury objev\u00ed chyba nebo nesoulad mezi n\u00e1zvy souboru a ulo\u017eenou procedurou, pak <code>deployDump<\/code> se neprovede a zobraz\u00ed text chyby. Neshoda ulo\u017een\u00fdch procedur mezi dumpem a aktu\u00e1ln\u00ed DB je nemo\u017en\u00e1 p\u0159i pou\u017eit\u00ed <code>deployDump<\/code>.<\/p>\n<p><\/p>\n<blockquote><p>P\u0159i vytv\u00e1\u0159en\u00ed nov\u00e9 ulo\u017een\u00e9 procedury nen\u00ed nutn\u00e9 ru\u010dn\u011b zad\u00e1vat spr\u00e1vn\u00fd n\u00e1zev souboru. Sta\u010d\u00ed, aby m\u011bl soubor p\u0159\u00edponu <code>.sql<\/code>. Po vyvol\u00e1n\u00ed <code>deployDump<\/code> bude text chyby obsahovat spr\u00e1vn\u00fd n\u00e1zev, kter\u00fd lze pou\u017e\u00edt pro p\u0159ejmenov\u00e1n\u00ed souboru.<\/p><\/blockquote>\n<p><code>deployDump<\/code> umo\u017e\u0148uje m\u011bnit parametry funkce nebo n\u00e1vratov\u00fd typ bez dal\u0161\u00edch krok\u016f, zat\u00edmco p\u0159i klasick\u00e9m p\u0159\u00edstupu by bylo nutn\u00e9<br \/>\nnejprve prov\u00e9st <code>DROP FUNCTION<\/code>, a teprve pot\u00e9 <code>CREATE OR REPLACE FUNCTION<\/code>.<\/p>\n<p><\/p>\n<p>Bohu\u017eel existuj\u00ed situace, kdy <code>deployDump<\/code> nen\u00ed mo\u017en\u00e9 automaticky aplikovat zm\u011bny. Nap\u0159\u00edklad pokud je odstran\u011bna trigger funkce, kter\u00e1 je pou\u017e\u00edv\u00e1na alespo\u0148 jedn\u00edm triggem. Takov\u00e9 situace se \u0159e\u0161\u00ed ru\u010dn\u011b pomoc\u00ed migra\u010dn\u00edch soubor\u016f.<\/p>\n<p><\/p>\n<p>Pokud za p\u0159enos zm\u011bn ve stored procedures odpov\u00edd\u00e1 s\u00e1m <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/schema-keeper\/schema-keeper\">schema-keeper<\/a><\/noindex>, pak pro p\u0159enos ostatn\u00edch zm\u011bn ve struktu\u0159e je nutn\u00e9 pou\u017e\u00edt migra\u010dn\u00ed soubory. Nap\u0159\u00edklad dobrou knihovnou pro pr\u00e1ci s migracemi je <noindex><a rel=\"nofollow\" href=\"https:\/\/packagist.org\/packages\/doctrine\/migrations\">doctrine\/migrations<\/a><\/noindex>.<\/p>\n<p><\/p>\n<p>Migrace by m\u011bly b\u00fdt aplikov\u00e1ny p\u0159ed spu\u0161t\u011bn\u00edm <code>deployDump<\/code>. To umo\u017e\u0148uje prov\u00e9st v\u0161echny zm\u011bny ve struktu\u0159e a vy\u0159e\u0161it probl\u00e9mov\u00e9 situace, aby se zm\u011bny ve stored procedures pozd\u011bji p\u0159enesly bez probl\u00e9m\u016f.<\/p>\n<p><\/p>\n<p>Podrobn\u011bji se pr\u00e1ce s migracemi pop\u00ed\u0161e v n\u00e1sleduj\u00edc\u00edch sekc\u00edch.<\/p>\n<p><\/p>\n<h2 id=\"kak-naladit-process-parallelnoy-raboty-nad-proektom-neskolkih-razrabotchikov\">Jak nastavit proces paraleln\u00ed pr\u00e1ce na projektu pro v\u00edce v\u00fdvoj\u00e1\u0159\u016f<\/h2>\n<p><\/p>\n<p>Je nutn\u00e9 vytvo\u0159it skript pro kompletn\u00ed inicializaci datab\u00e1ze, kter\u00fd bude spu\u0161t\u011bn v\u00fdvoj\u00e1\u0159em na jeho pracovn\u00edm stroji, aby se struktura lok\u00e1ln\u00ed datab\u00e1ze uvedla do souladu se z\u00e1lohou ulo\u017eenou ve VCS. Nejjednodu\u0161\u0161\u00ed je rozd\u011blit inicializaci lok\u00e1ln\u00ed datab\u00e1ze do t\u0159ech krok\u016f:<\/p>\n<p><\/p>\n<ol>\n<li>Import souboru s z\u00e1kladn\u00ed strukturou, kter\u00fd se bude jmenovat nap\u0159\u00edklad <code>base.sql<\/code> <\/li>\n<li>Aplikace migrac\u00ed<\/li>\n<li>Zavol\u00e1n\u00ed <code>deployDump<\/code><\/li>\n<\/ol>\n<p><\/p>\n<blockquote><p><code>base.sql<\/code> \u2014 to je v\u00fdchoz\u00ed bod, na kter\u00fd se aplikuj\u00ed migrace a prov\u00e1d\u00ed se <code>deployDump<\/code>, to znamen\u00e1 <code>base.sql + migrace + deployDump = aktu\u00e1ln\u00ed struktura datab\u00e1ze<\/code>. Takov\u00fd soubor lze vytvo\u0159it pomoc\u00ed utilit. <code>pg_dump<\/code>Pou\u017e\u00edv\u00e1 se <code>base.sql<\/code> v\u00fdhradn\u011b p\u0159i inicializaci datab\u00e1ze od nuly.<\/p><\/blockquote>\n<p>Nazveme skript pro kompletn\u00ed inicializaci datab\u00e1ze <code>refresh.sh<\/code>. Pracovn\u00ed proces m\u016f\u017ee vypadat n\u00e1sledovn\u011b:<\/p>\n<p><\/p>\n<ol>\n<li>V\u00fdvoj\u00e1\u0159 spust\u00ed ve sv\u00e9m prost\u0159ed\u00ed <code>refresh.sh<\/code> a z\u00edsk\u00e1 aktu\u00e1ln\u00ed strukturu datab\u00e1ze.<\/li>\n<li>V\u00fdvoj\u00e1\u0159 za\u010dne pracovat na zadan\u00e9m \u00fakolu, modifikuje lok\u00e1ln\u00ed datab\u00e1zi podle pot\u0159eb nov\u00e9 funkce (<code>ALTER TABLE ... ADD COLUMN<\/code> atd.)<\/li>\n<li>Po dokon\u010den\u00ed \u00fakolu v\u00fdvoj\u00e1\u0159 zavol\u00e1 funkci <code>saveDump<\/code>, aby zapsal do VCS zm\u011bny proveden\u00e9 v datab\u00e1zi.<\/li>\n<li>V\u00fdvoj\u00e1\u0159 znovu spust\u00ed <code>refresh.sh<\/code>, pot\u00e9 <code>verifyDump<\/code>, kter\u00fd nyn\u00ed zobrazuje seznam zm\u011bn k zahrnut\u00ed do migrace.<\/li>\n<li>V\u00fdvoj\u00e1\u0159 p\u0159evede v\u0161echny zm\u011bny struktury do migra\u010dn\u00edho souboru, spust\u00ed znovu <code>refresh.sh<\/code> a <code>verifyDump<\/code>, a pokud je migrace spr\u00e1vn\u011b vytvo\u0159ena, <code>verifyDump<\/code> uk\u00e1\u017ee absenci rozd\u00edl\u016f mezi lok\u00e1ln\u00ed datab\u00e1z\u00ed a ulo\u017eenou z\u00e1lohou.<\/li>\n<\/ol>\n<p><\/p>\n<p>Popisovan\u00fd proces je kompatibiln\u00ed s principy gitflow. Ka\u017ed\u00e1 v\u011btev v VCS bude obsahovat svou vlastn\u00ed verzi dumpu, a p\u0159i slou\u010den\u00ed v\u011btv\u00ed dojde ke slou\u010den\u00ed dump\u016f. V\u011bt\u0161inou nen\u00ed pot\u0159eba po slou\u010den\u00ed prov\u00e1d\u011bt \u017e\u00e1dn\u00e9 dal\u0161\u00ed akce, ale pokud do\u0161lo ke zm\u011bn\u00e1m v r\u016fzn\u00fdch v\u011btv\u00edch, nap\u0159\u00edklad ve stejn\u00e9 tabulce, m\u016f\u017ee nastat konflikt.<\/p>\n<p><\/p>\n<p>Zva\u017eme konfliktn\u00ed situaci na p\u0159\u00edkladu: existuje v\u011btev <em>develop<\/em>, od kter\u00e9 se odvojuj\u00ed dv\u011b v\u011btve: <em>feature1<\/em> a <em>feature2<\/em>, kter\u00e9 nemaj\u00ed konflikty s <em>develop<\/em>, ale maj\u00ed konflikty mezi sebou. \u00dakolem je prov\u00e9st slou\u010den\u00ed obou v\u011btv\u00ed do <em>develop<\/em>. V takov\u00e9m p\u0159\u00edpad\u011b se doporu\u010duje nejprve prov\u00e9st slou\u010den\u00ed jedn\u00e9 z v\u011btv\u00ed do <em>develop<\/em>, a pot\u00e9 slou\u010den\u00ed <em>develop<\/em> do zb\u00fdvaj\u00edc\u00ed v\u011btve, p\u0159i\u010dem\u017e se vy\u0159e\u0161\u00ed konflikty v t\u00e9to zb\u00fdvaj\u00edc\u00ed v\u011btvi, a nakonec prov\u00e9st slou\u010den\u00ed posledn\u00ed v\u011btve do <em>develop<\/em>. B\u011bhem f\u00e1ze \u0159e\u0161en\u00ed konflikt\u016f bude mo\u017en\u00e1 t\u0159eba upravit migra\u010dn\u00ed soubor v posledn\u00ed v\u011btvi, aby odpov\u00eddal kone\u010dn\u00e9mu dumpu zahrnuj\u00edc\u00edmu v\u00fdsledky slou\u010den\u00ed.<\/p>\n<p><\/p>\n<h2 id=\"kak-bezopasno-deploit-bolshee-kolichestvo-izmeneniy-v-strukture-bd-na-production-okruzhenie\">Jak bezpe\u010dn\u011b nasazovat v\u011bt\u0161\u00ed mno\u017estv\u00ed zm\u011bn ve struktu\u0159e datab\u00e1ze na produk\u010dn\u00ed prost\u0159ed\u00ed<\/h2>\n<p><\/p>\n<p>D\u00edky tomu, \u017ee VCS obsahuje dump aktu\u00e1ln\u00ed struktury DB, je mo\u017en\u00e9 zkontrolovat produk\u010dn\u00ed datab\u00e1zi na p\u0159esn\u00e9 dodr\u017een\u00ed po\u017eadovan\u00e9 struktury. To zaru\u010duje, \u017ee se do produk\u010dn\u00ed datab\u00e1ze \u00fasp\u011b\u0161n\u011b p\u0159enesly v\u0161echny zm\u011bny, kter\u00e9 zam\u00fd\u0161leli v\u00fdvoj\u00e1\u0159i.<\/p>\n<p><\/p>\n<p>Proto\u017ee <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/ddl.html\">DDL<\/a><\/noindex> v PostgreSQL je <noindex><a rel=\"nofollow\" href=\"https:\/\/wiki.postgresql.org\/wiki\/Transactional_DDL_in_PostgreSQL:_A_Competitive_Analysis\">transak\u010dn\u00ed<\/a><\/noindex>, doporu\u010duje se dodr\u017eovat n\u00e1sleduj\u00edc\u00ed po\u0159ad\u00ed nasazen\u00ed, aby bylo mo\u017en\u00e9 v p\u0159\u00edpad\u011b nep\u0159edv\u00eddan\u00e9 chyby prov\u00e9st \u201ebezbolestn\u011b\u201c <code>ROLLBACK<\/code>:<\/p>\n<p><\/p>\n<ol>\n<li>Zah\u00e1jit transakci<\/li>\n<li>V transakci prov\u00e9st v\u0161echny migrace<\/li>\n<li>Ve stejn\u00e9 transakci prov\u00e9st <code>deployDump<\/code><\/li>\n<li>Neukon\u010duj\u00edc\u00ed transakci prov\u00e9st <code>verifyDump<\/code>. Pokud nejsou \u017e\u00e1dn\u00e9 chyby, prov\u00e9st <code>COMMIT<\/code>. Pokud jsou chyby, prov\u00e9st <code>ROLLBACK<\/code><\/li>\n<\/ol>\n<p><\/p>\n<p>Tyto kroky se pom\u011brn\u011b snadno integruj\u00ed do st\u00e1vaj\u00edc\u00edch p\u0159\u00edstup\u016f k nasazen\u00ed aplikac\u00ed, v\u010detn\u011b zero-downtime.<\/p>\n<p><\/p>\n<h1 id=\"zaklyuchenie\">Z\u00e1v\u011br<\/h1>\n<p><\/p>\n<p>D\u00edky v\u00fd\u0161e uveden\u00fdm metod\u00e1m je mo\u017en\u00e9 vyt\u011b\u017eit maximum v\u00fdkonu z projekt\u016f \u201ePHP + PostgreSQL\u201c, a to na \u00fakor relativn\u011b mal\u00e9ho mno\u017estv\u00ed pohodl\u00ed p\u0159i v\u00fdvoji ve srovn\u00e1n\u00ed s implementac\u00ed cel\u00e9 obchodn\u00ed logiky v hlavn\u00edm k\u00f3du aplikace. Nav\u00edc zpracov\u00e1n\u00ed dat v <noindex><a rel=\"nofollow\" href=\"https:\/\/www.postgresql.org\/docs\/current\/plpgsql.html\">PL\/pgSQL<\/a><\/noindex> \u010dasto vypad\u00e1 transparentn\u011bji a vy\u017eaduje m\u00e9n\u011b k\u00f3du ne\u017e stejn\u00e1 funkcionalita napsan\u00e1 v PHP.<\/p>\n<p>Zdroj: <a content=\"nofollow\" rel=\"nofollow\" href=\"https:\/\/habr.com\/ru\/post\/447746\/\">habr.com<\/a><\/p>","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"excerpt":{"rendered":"<p>\u0426\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u2014 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 schema-keeper \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e \u043e\u0431\u043b\u0435\u0433\u0447\u0438\u0442\u044c \u043f\u0440\u043e\u0446\u0435\u0441\u0441 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0438 \u0431\u0430\u0437 \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 PHP-\u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0449\u0438\u0445 \u0421\u0423\u0411\u0414 PostgreSQL. \u0418\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044f \u0438\u0437 \u044d\u0442\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438, \u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c, \u0431\u0443\u0434\u0435\u0442 \u043f\u043e\u043b\u0435\u0437\u043d\u0430 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e \u043c\u0430\u043a\u0441\u0438\u043c\u0443\u043c\u0443 \u0445\u043e\u0442\u044f\u0442 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0432\u043e\u0437\u043c\u043e\u0436\u043d\u043e\u0441\u0442\u0438 PostgreSQL, \u043d\u043e \u0441\u0442\u0430\u043b\u043a\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u0441 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u043c\u0438 \u0441\u043e\u043f\u0440\u043e\u0432\u043e\u0436\u0434\u0435\u043d\u0438\u044f \u0431\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0438, \u0432\u044b\u043d\u0435\u0441\u0435\u043d\u043d\u043e\u0439 \u0432 \u0411\u0414. \u0421\u0442\u0430\u0442\u044c\u044f \u043d\u0435 \u0431\u0443\u0434\u0435\u0442 \u043e\u043f\u0438\u0441\u044b\u0432\u0430\u0442\u044c \u043f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430 [&hellip;]<\/p>\n","protected":false,"gt_translate_keys":[{"key":"rendered","format":"html"}]},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[688],"tags":[],"class_list":["post-31385","post","type-post","status-publish","format-standard","hentry","category-administrirovanie"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 5.0.3 - aioseo.com -->\n\t<meta name=\"description\" content=\"\u0426\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u2014 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 schema-keeper \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e.\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Yuri Gagarin\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/prohoster.info\/cs\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper\" \/>\n\t\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 5.0.3\" \/>\n\t\t<meta property=\"og:locale\" content=\"cs_CZ\" \/>\n\t\t<meta property=\"og:site_name\" content=\"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"\ud83e\udd47\u0411\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430 \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 SchemaKeeper | ProHoster\" \/>\n\t\t<meta property=\"og:description\" content=\"\u0426\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u2014 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 schema-keeper \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e.\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/prohoster.info\/cs\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper\" \/>\n\t\t<meta property=\"og:image\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:secure_url\" content=\"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg\" \/>\n\t\t<meta property=\"og:image:width\" content=\"350\" \/>\n\t\t<meta property=\"og:image:height\" content=\"350\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2019-10-31T18:40:58+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2019-10-31T18:40:58+00:00\" \/>\n\t\t<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<meta property=\"article:author\" content=\"https:\/\/www.facebook.com\/prohoster\" \/>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"\ud83e\udd47Obchodn\u00ed logika v datab\u00e1zi pomoc\u00ed SchemaKeeper | ProHoster","description":"C\u00edlem tohoto \u010dl\u00e1nku je na p\u0159\u00edkladu knihovny schema-keeper uk\u00e1zat n\u00e1stroje, kter\u00e9 umo\u017e\u0148uj\u00ed v\u00fdznamn\u011b.","canonical_url":"https:\/\/prohoster.info\/cs\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":null,"og:locale":"cs_CZ","og:site_name":"ProHoster | \u041a\u0443\u043f\u0438\u0442\u044c \u043d\u0430\u0434\u0435\u0436\u043d\u044b\u0439 \u0445\u043e\u0441\u0442\u0438\u043d\u0433 \u0434\u043b\u044f \u0441\u0430\u0439\u0442\u043e\u0432 \u0441 \u0437\u0430\u0449\u0438\u0442\u043e\u0439 \u043e\u0442 DDoS, VPS VDS \u0441\u0435\u0440\u0432\u0435\u0440\u044b","og:type":"article","og:title":"\ud83e\udd47\u0411\u0438\u0437\u043d\u0435\u0441-\u043b\u043e\u0433\u0438\u043a\u0430 \u0432 \u0431\u0430\u0437\u0435 \u0434\u0430\u043d\u043d\u044b\u0445 \u043f\u0440\u0438 \u043f\u043e\u043c\u043e\u0449\u0438 SchemaKeeper | ProHoster","og:description":"\u0426\u0435\u043b\u044c \u0434\u0430\u043d\u043d\u043e\u0439 \u0441\u0442\u0430\u0442\u044c\u0438 \u2014 \u043d\u0430 \u043f\u0440\u0438\u043c\u0435\u0440\u0435 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 schema-keeper \u043f\u043e\u043a\u0430\u0437\u0430\u0442\u044c \u0438\u043d\u0441\u0442\u0440\u0443\u043c\u0435\u043d\u0442\u044b, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u044e\u0442 \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0435\u043d\u043d\u043e.","og:url":"https:\/\/prohoster.info\/cs\/blog\/administrirovanie\/biznes-logika-v-baze-dannyh-pri-pomoshhi-schemakeeper","og:image":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:secure_url":"https:\/\/prohoster.info\/wp-content\/uploads\/2021\/11\/logo-350.jpg","og:image:width":350,"og:image:height":350,"article:published_time":"2019-10-31T18:40:58+00:00","article:modified_time":"2019-10-31T18:40:58+00:00","article:publisher":"https:\/\/www.facebook.com\/prohoster","article:author":"https:\/\/www.facebook.com\/prohoster"},"aioseo_meta_data":{"post_id":"31385","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"local_seo":null,"seo_analyzer_scan_date":"2026-01-21 05:54:24","breadcrumb_settings":null,"limit_modified_date":false,"reviewed_by":null,"ai":null,"created":"2021-03-01 03:17:26","updated":"2026-01-21 05:54:24","focus_keyword":null,"additional_keywords":null,"truseo_locale":null},"gt_translate_keys":[{"key":"link","format":"url"}],"_links":{"self":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/posts\/31385","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/comments?post=31385"}],"version-history":[{"count":0,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/posts\/31385\/revisions"}],"wp:attachment":[{"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/media?parent=31385"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/categories?post=31385"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/prohoster.info\/cs\/wp-json\/wp\/v2\/tags?post=31385"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}