abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
    dnes 13:33 | Nová verze

    Vyšlo Pharo 12.0, programovací jazyk a vývojové prostředí s řadou pokročilých vlastností. Krom tradiční nadílky oprav přináší nový systém správy ladících bodů, nový způsob definice tříd, prostor pro objekty, které nemusí procházet GC a mnoho dalšího.

    Pavel Křivánek | Komentářů: 0
    dnes 04:55 | Zajímavý software

    Microsoft zveřejnil na GitHubu zdrojové kódy MS-DOSu 4.0 pod licencí MIT. Ve stejném repozitáři se nacházejí i před lety zveřejněné zdrojové k kódy MS-DOSu 1.25 a 2.0.

    Ladislav Hagara | Komentářů: 18
    včera 17:33 | Nová verze

    Canonical vydal (email, blog, YouTube) Ubuntu 24.04 LTS Noble Numbat. Přehled novinek v poznámkách k vydání a také příspěvcích na blogu: novinky v desktopu a novinky v bezpečnosti. Vydány byly také oficiální deriváty Edubuntu, Kubuntu, Lubuntu, Ubuntu Budgie, Ubuntu Cinnamon, Ubuntu Kylin, Ubuntu MATE, Ubuntu Studio, Ubuntu Unity a Xubuntu. Jedná se o 10. LTS verzi.

    Ladislav Hagara | Komentářů: 13
    včera 14:22 | Komunita

    Na YouTube je k dispozici videozáznam z včerejšího Czech Open Source Policy Forum 2024.

    Ladislav Hagara | Komentářů: 2
    včera 13:22 | Nová verze

    Fossil (Wikipedie) byl vydán ve verzi 2.24. Jedná se o distribuovaný systém správy verzí propojený se správou chyb, wiki stránek a blogů s integrovaným webovým rozhraním. Vše běží z jednoho jediného spustitelného souboru a uloženo je v SQLite databázi.

    Ladislav Hagara | Komentářů: 0
    včera 12:44 | Nová verze

    Byla vydána nová stabilní verze 6.7 webového prohlížeče Vivaldi (Wikipedie). Postavena je na Chromiu 124. Přehled novinek i s náhledy v příspěvku na blogu. Vypíchnout lze Spořič paměti (Memory Saver) automaticky hibernující karty, které nebyly nějakou dobu používány nebo vylepšené Odběry (Feed Reader).

    Ladislav Hagara | Komentářů: 0
    včera 04:55 | Nová verze

    OpenJS Foundation, oficiální projekt konsorcia Linux Foundation, oznámila vydání verze 22 otevřeného multiplatformního prostředí pro vývoj a běh síťových aplikací napsaných v JavaScriptu Node.js (Wikipedie). V říjnu se verze 22 stane novou aktivní LTS verzí. Podpora je plánována do dubna 2027.

    Ladislav Hagara | Komentářů: 0
    včera 04:22 | Nová verze

    Byla vydána verze 8.2 open source virtualizační platformy Proxmox VE (Proxmox Virtual Environment, Wikipedie) založené na Debianu. Přehled novinek v poznámkách k vydání a v informačním videu. Zdůrazněn je průvodce migrací hostů z VMware ESXi do Proxmoxu.

    Ladislav Hagara | Komentářů: 0
    včera 04:11 | Nová verze

    R (Wikipedie), programovací jazyk a prostředí určené pro statistickou analýzu dat a jejich grafické zobrazení, bylo vydáno ve verzi 4.4.0. Její kódové jméno je Puppy Cup.

    Ladislav Hagara | Komentářů: 0
    24.4. 22:44 | IT novinky

    IBM kupuje společnost HashiCorp (Terraform, Packer, Vault, Boundary, Consul, Nomad, Waypoint, Vagrant, …) za 6,4 miliardy dolarů, tj. 35 dolarů za akcii.

    Ladislav Hagara | Komentářů: 14
    KDE Plasma 6
     (73%)
     (9%)
     (2%)
     (16%)
    Celkem 787 hlasů
     Komentářů: 4, poslední 6.4. 15:51
    Rozcestník

    Dotaz: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql

    4.4.2015 07:12 bek
    Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Přečteno: 866×
    Ahoj. Pokud je k mé aplikaci veliké množství přístupů najednou, pak se čas od času objeví chyba "There is no active transaction". V PHP používám "vnořování" transakcí pomocí obalové třídy nad PDO, konkrétně metody:
    	public function beginTransaction() {
    		if ($this->transLevel === 0) {
    			$this->connection->beginTransaction();
    		} else {
    			$this->connection->exec("SAVEPOINT LEVEL{$this->transLevel}");
    		}
    		$this->transLevel++;
    	}
    
    	public function commit() {
    		$this->transLevel--;
    		if ($this->transLevel <= 0) {
    			$this->transLevel = 0;
    			$this->connection->commit();
    		} else {
    			$this->connection->exec("RELEASE SAVEPOINT LEVEL{$this->transLevel}");
    		}
    	}
    
    	public function rollBack() {
    		$this->transLevel--;
    		if ($this->transLevel <= 0) {
    			$this->transLevel = 0;
    			$this->connection->rollBack();
    		} else {
    			$this->connection->exec("ROLLBACK TO SAVEPOINT LEVEL{$this->transLevel}");
    		}
    	}
    
    V kódu se to používá takto:
    for ($raceI = 0; $raceI <= 10; $raceI++) {
    	$inTransaction = false;
    	try {
    		$this->dbConnection->beginTransaction();
    		$inTransaction = true;
    
    		... NEJAKE DOTAZY, KTERE MOHOU ROVNEZ OBSAHOVAT TAKOVE KONSTRUKCE
    
    		$this->dbConnection->commit();
    		break;
    	} catch (\PDOException $e) {
    		if ($inTransaction) {
    			$this->dbConnection->rollBack();
    		}
    		if ($e->getCode() != 40001 || $raceI === 10) { // pouzivam serialize izolaci, proto vice pokusu
    			throw $e;
    		}	
    	}
    }
    
    Konkrétní problém je ten, že očividně proběhne někdy více rollbacků než je otevřených transakcí. Co mám na tomto kódu špatně? Jedině snad, že by beginTransaction ve skutečnosti někdy tiše selhala, ale to snad není ani možné ne?

    Odpovědi

    5.4.2015 03:14 bek
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Tak jsem na to asi přišel. I commit může vrátit chybu a postgresql může samo od sebe ukončit transakci, proto rollBack už nefunguje, když na commitu se to ukončilo. Po dlouhém debugování jsem přišel na to, že před tou chybou se objeví:
    SQLSTATE[40001]: Serialization failure: 7 ERROR:  could not serialize access due to read/write dependencies among transactions
    DETAIL:  Reason code: Canceled on identification as a pivot, during commit attempt.
    Poradí mi někdo zkušený, zda je zaručeno, že commit zkončený chybou vždy způsobí ukončení transakce resp. daného SAVEPOINT?
    okbob avatar 5.4.2015 07:55 okbob | skóre: 30 | blog: systemakuv_blog | Benešov
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Podle dokumentace by to tak mělo být http://www.postgresql.org/docs/9.4/static/sql-begin.html
    Use COMMIT or ROLLBACK to terminate a transaction block.
    5.4.2015 09:23 bek
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    OK, díky. Mimochodem toto odhalilo i ten fakt, že se občas nějaká transakce nepovede ani pokud ji opakuji třeba 20x. Konkrétně se jedná o problémy při SELECTU. Zkoušel jsem dávat i sleep mezi opakování transakce, rovněž bez úspěchu. Problém občas nastává při současném připojení k aplikaci. Vzhledem k tomu, že se mi zaloguje jen jeden error, tak to znamená, že selže transakce pouze na jednom spojení a na ostatních se po zopakování provedou. Dá se tohle nějak pořešit? Snižovat úroveň transakcí není dobré řešení.
    5.4.2015 12:02 Kit | skóre: 45 | Brno
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Při SELECTu přece transakci nepotřebuješ.
    Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
    7.4.2015 18:22 j
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Zalezi co selectuje a jak to pak hodla pouzit.
    okbob avatar 5.4.2015 13:30 okbob | skóre: 30 | blog: systemakuv_blog | Benešov
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Chyba "serialization failure" znamená, že došlo k race condition, a že je nutné transakci zopakovat. Na úrovni izolace transakce SERIALIZATION je tato chyba běžná. Jediné, co je možné, je nespoléhat se na Postgres, a přejít na úroveň REPEATABLE READ, a race condition si pořešit ručně pomocí SELECT FOR UPDATE - cenou je asi potenciálně větší čekání na zámky.
    5.4.2015 14:00 Kit | skóre: 45 | Brno
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Obávám se, že jen dělá jednu ze základních chyb: Dělá SELECT jen proto, aby na základě získaných dat provedl UPDATE.
    Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
    okbob avatar 5.4.2015 14:31 okbob | skóre: 30 | blog: systemakuv_blog | Benešov
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Což SERIALIZABLE řeší - za cenu, že to občas řízeně spadne.
    5.4.2015 18:18 bek
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Pouze v 1 případě. V transakci mi to běží proto, že potřebuji konzistentní pohled na data bez fantomů během načítání dat do ORM. Příklad:
    1. Zahájím transakci
    2. SELECT id FROM tabulka1 INNER JOIN ... INNER JOIN ... WHERE sloupec NOT IN (SELECT MAX .. FROM) .. AND sloupec2 < ...
    3. Pro každý vrácený výsledek načtu objekty: ...findById(id) - i tato fce používá různé agregace při načítání
    4. Ukončím transakci
    Možná to jen špatně chápu a stačilo by mi REPEATABLE READ. Mám záruku, že 2x načtu stejná data za stejných podmínek i kdyby ta data jiná transakce zatím mazala jinde? Vím, že v postgresql by i REPEATABLE READ mělo být bez fantomů, ale na http://www.postgresql.org/docs/9.1/static/transaction-iso.html je v 13.2.3 příklad s počítáním SUM, který chápu tak, že pokud transakce A provede úpravu, pak to může ovlivnit i druhou běžící transakci. Nebo jak to je?
    5.4.2015 18:54 Filip Jirsák
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Repeatable read vidí stav databáze, jaký byl v okamžiku začátku transakce. Při opakovaném čtení v jedné transakci tedy budete dostávat stejná data (proto se to jmenuje repeatable read).

    Ten příklad neznamená, že by se transakce navzájem ovlivňovaly, právě naopak - při repeatable read se může stát, že ta transakce A nijak neovlivní transakci B, přestože by asi bylo žádoucí, aby ji ovlivnila.
    5.4.2015 19:28 Kit | skóre: 45 | Brno
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Aha. Když používáš ORM, tak se tomu asi nevyhneš...
    Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
    okbob avatar 5.4.2015 20:36 okbob | skóre: 30 | blog: systemakuv_blog | Benešov
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    samotný select to nezpůsobí - někde musíte používat UPDATE, INSERT - ve vašem kódu dochází k potenciálním race condition. Můžete jim předejít REPEATABLE READ a explicitním zamykáním.
    5.4.2015 21:45 bek
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    To asi ano, jenže díky tomu pak selže i ten select.
    okbob avatar 6.4.2015 08:08 okbob | skóre: 30 | blog: systemakuv_blog | Benešov
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    To je na databázi, kterou transakci vybere jako tu špatnou - a kterou zabije. Případně můžete optimalizovat způsob práce - a transakce, které jsou čistě čtecí omarkovat jako READ ONLY.
    5.4.2015 23:36 Filip Jirsák
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Předpokládám, že aktualizace se provádějí v jiné transakci, než čtení. Takže stejně musí mít ošetřeno, že se mezi transakcemi nezměnila data, která chce aktualizovat - k tomu izolace transakce nestačí.
    6.4.2015 00:22 bek
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Myslíte detekci změn probíhajících mimo transakce? Tzn. uživatel A načte objekt (ORM), uživatel B načte objekt, uživatel A uloží objekt, uživatel B nemůže, protože někdo jiný něco změnil? To mám ošetřeno zvlášť hlídáním hodnoty sloupce určujícím verzi dat.
    okbob avatar 6.4.2015 08:05 okbob | skóre: 30 | blog: systemakuv_blog | Benešov
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Tak pak možná nepotřebujete SERIALIZABLE
    okbob avatar 6.4.2015 08:06 okbob | skóre: 30 | blog: systemakuv_blog | Benešov
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Nový SERIALIZABLE level (počínaje 9.2) by na to stačit měl.
    6.4.2015 09:46 Filip Jirsák
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Když uživatel A načte v transakci 1 stav účtu X do webového formuláře, uživatel B načte v transakci 2 stav účtu X do webového formuláře, uživatel A k zůstatku na účtu X přičte 10 Kč a v transakci 3 zůstatek uloží, a konečně uživatel B přičte k zůstatku na účtu X 10 Kč a v transakci 4 to uloží, žádná úroveň izolace transakcí to nezachrání a vždy budete mít na účtu X na konci +10 Kč a ne +20 Kč. Protože k tomu konkurenčnímu přístupu došlo mimo transakce a mimo databázi.

    Samozřejmě existují jednoduché způsoby, jak tohle opravit, ale izolace transakcí v databázi s tím opravdu nic neudělá. Jedině že byste měl transakci od načtení dat až po jejich zápis. Jenže transakce zahrnující interakci s uživatelem, zvlášť s uživatelem u webového prohlížeče, u kterého nevíte, jestli tam ještě sedí a dumá nad tím číslem, nebo jestli už vytáhl počítač ze zásuvky a šel domů - taková transakce spolehlivě zlikviduje jakýkoli systém.
    okbob avatar 6.4.2015 11:21 okbob | skóre: 30 | blog: systemakuv_blog | Benešov
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    To už je jiná situace, která je za hranicí toho, co řeší ACID. I když si myslím, že by se to dalo na ACID napasovat - jen se musí vždy přehrát celá sekvence SQL příkazů.
    okbob avatar 6.4.2015 11:31 okbob | skóre: 30 | blog: systemakuv_blog | Benešov
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Což, když si to tak promítnu vede trochu i k optimistickému zamykání.
    7.4.2015 18:27 j
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Tohle se ovsem resi zcela trivialne tak, ze ani uzivatel A ani uzivatel B nedela zadny update, ale oba udelaji insert. V databazi pak muze byt sumarni pole, ktere vyjadruje stav k nejakemu okamziku, ale zaroven mam kdykoli zcela aktualni stav, vcetne historie zmen.
    6.4.2015 00:41 Ivan
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    na tohle prece skore zadnou transakci nepotrebujes, vzdyt jde o samy cteni. nestacilo by jen pouzit `select max .. for update` u tabulky u ktere se pouziva not in. Tim by se to synchronizovalo, konkretni idcka by se zamknuly a commit na konci transakce by je zase odemknul.

    PS: co je to za ORM, ze nezvladne konzistentni nacitani sam?
    6.4.2015 07:45 bek
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Často se zapisuje, ale většinou havaruje to čtení kvůli souběžnému zápisu. ORM používám takovou vlastní implementaci a ne na všechno, jinak by to bylo pomalé. To, že to teď občas havarovalo kvůli SERIALIZABLE spíš značí, že můj testovací stroj má slabý HW, zase díky tomu je to dobré na testování. No nicméně jsem přepnul na REPEATABLE READ s explicitním zamykáním určitých řádků a je to už OK. I když je SERIALIZABLE bezpečnější, tak se zdá nemohu moc použít. Ona ta postgresql implementace REPEATABLE READ jak jsem prozkoumal postačí.
    6.4.2015 09:35 Filip Jirsák
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Nikoli, to, že transakce SERIALIZABLE občas nedoběhne kvůli konkurenčnímu přístupu, to není kvůli slabému hardwaru, to je prostě vlastnost této úrovně izolace transakcí. Stejně tak může skončit chybou i REPEATABLE READ. Transakce vám nijak nepomůžou, když nevíte, jak je používat - a vnořování transakcí to nezachrání. Prostě když používáte SERIALIZABLE nebo REPEATABLE READ, musíte počítat s tím, že transakce může selhat, a v aplikaci na to nějak zareagovat. Zrovna při čtení dat je to triviální, prostě tu čtecí sekvenci spustíte znova od začátku.
    6.4.2015 18:36 bek
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    To ano, ale na silnějším hw je větší šance, že po zopakování proběhne. protože se jiná rychleji dokončí - kromě toho teď debuguji také tím, že hromady logů zapisuji do databáze (někdy stovky řádků za vteřinu) a analyzuji - běžný soubor už by to nedával. Proto to také HW ne úplně stíhá. To, že budu muset transakce opakovat vím, s tím jsem počítal u SERIALIZABLE. Stejně mě ale chování postgresql dokázalo překvapit, do teď jsem dělal s mysql. Ale po přepnutí na REPEATABLE READ to funguje perfektně. Mělo by to stačit a snad tato úroveň opravdu v postgresql vylučuje fantomy.
    6.4.2015 21:16 bek
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Děkuji všem za reakce. Znovu jsem si přečetl dokumentace nejnovější verze postgresql a už jsem tu jejich implementaci myslím dostatečně pochopil. Musím uznat, že jsem byl trochu zmatený tím, že jsem doteď dělal s mysql a popis transakcí v postgresql jsem původně evidentně studoval podle dokumentace k verzím, kdy SERIALIZABLE bylo ještě implementováno jako REPEATABLE READ. Celé jsem to vyřešil přepnutím na REPEATABLE READ. Takže vzhledem k tomu, že při návrhu aplikace jsem počítal s tím, že SERIALIZABLE funguje jako REPEATABLE READ, tak to nevadí.
    9.4.2015 13:05 podlesh | skóre: 38 | Freiburg im Breisgau
    Rozbalit Rozbalit vše Re: Jak správně ošetřit transakce a jejich chybové hodnoty v potgresql
    Pokud aplikace používá Postgresql, tak by měla být napsána tak aby se každá transakce dala automaticky zopakovat. Nejelegantnější je nějaká forma AOP nebo funkcionálně.

    Založit nové vláknoNahoru

    Tiskni Sdílej: Linkuj Jaggni to Vybrali.sme.sk Google Del.icio.us Facebook

    ISSN 1214-1267   www.czech-server.cz
    © 1999-2015 Nitemedia s. r. o. Všechna práva vyhrazena.