abclinuxu.cz AbcLinuxu.cz itbiz.cz ITBiz.cz HDmag.cz HDmag.cz abcprace.cz AbcPráce.cz
AbcLinuxu hledá autory!
Inzerujte na AbcPráce.cz od 950 Kč
Rozšířené hledání
×
eParkomat, startup z ČR, postoupil mezi finalisty evropského akcelerátoru ChallengeUp!
Robot na pivo mu otevřel dveře k opravdovému byznysu
Internet věcí: Propojený svět? Už se to blíží...
včera 17:02 | Pozvánky

Přijďte si popovídat o open source obecně a openSUSE konkrétně s dalšími uživateli a vývojáři. Oslava nového vydání openSUSE Leap se uskuteční 16. prosince od 17:00 v nových prostorách firmy SUSE v Praze. K dispozici bude nějaké občerstvení a DVD pro ty, kdo je sbírají nebo ještě mají mechaniku. Po párty v kanceláři se bude pokračovat v některé z hospod v okolí.

Miška | Komentářů: 7
včera 14:55 | Zajímavý software

Byla vydána verze Alpha 1.0 otevřeného operačního systému pro chytré hodinky AsteroidOS. Podporovány jsou hodinky LG G Watch, LG G Watch Urbane, Asus ZenWatch 2 a Sony Smartwatch 3. Ukázka ovládání hodinek na YouTube. Jaroslav Řezník přednášel o AsteroidOS na chytrých hodinkách (videozáznam) na letošní konferenci OpenAlt.

Ladislav Hagara | Komentářů: 0
včera 13:30 | Zajímavý software

Byly uvolněny zdrojové kódy známé rogue-like hry DoomRL. Počátky hry jsou v roce 2002. Je napsána ve FreePascalu a zdrojový kód je nyní k dispozici na GitHubu pod licencí GNU GPL 2.0. Autor pracuje na nové hře Jupiter Hell, která je moderním nástupcem DoomRL a na jejíž vývoj shání peníze prostřednictvím Kickstarteru.

Blaazen | Komentářů: 0
včera 13:15 | Pozvánky

Přijďte s námi oslavit vydání Fedory 25. Na programu budou přednášky o novinkách, diskuse, neřízený networking atd. Release Party se bude konat 16. prosince v prostorách společnosti Etnetera. Na party budou volně k dispozici také propagační materiály, nová DVD s Fedorou 25 a samozřejmě občerstvení. Přednášky budou probíhat v češtině. Pro více informací se můžete podívat na web MojeFedora.cz. Jen připomínám, že tentokrát jsme zavedli

… více »
frantisekz | Komentářů: 0
9.12. 16:38 | Komunita

Byly zveřejněny videozáznamy přednášek a workshopů z letošní konference OpenAlt konané 5. a 6. listopadu v Brně. K videozáznamům lze přistupovat ze stránky na SuperLectures nebo přes program konference, detaily o vybrané přednášce nebo workshopu a dále kliknutím na ikonku filmového pásu. Celkově bylo zpracováno 65 hodin z 89 přednášek a workshopů.

Ladislav Hagara | Komentářů: 0
9.12. 11:30 | Komunita

Bylo oznámeno, že bude proveden bezpečnostní audit zdrojových kódů open source softwaru pro implementaci virtuálních privátních sítí OpenVPN. Audit provede Matthew D. Green (blog), uznávaný kryptolog a profesor na Univerzitě Johnse Hopkinse. Auditována bude verze 2.4 (aktuálně RC 1, stabilní verze je 2.3.14). Audit bude financován společností Private Internet Access [reddit].

Ladislav Hagara | Komentářů: 4
9.12. 06:00 | Komunita

Na YouTube byl publikován Blender Institute Reel 2016, ani ne dvouminutový sestřih z filmů, které vznikly za posledních 10 let díky Blender Institutu. V institutu aktuálně pracují na novém filmu Agent 327. Dění kolem filmu lze sledovat na Blender Cloudu. Videoukázka Agenta 327 z června letošního roku na YouTube.

Ladislav Hagara | Komentářů: 0
9.12. 01:02 | Zajímavý článek

Minulý týden byly vydány verze 1.2.3 a 1.1.7 webového poštovního klienta Roundcube. V oznámení o vydání bylo zmíněno řešení bezpečnostního problému nalezeného společností RIPS a souvisejícího s voláním funkce mail() v PHP. Tento týden byly zveřejněny podrobnosti. Útočník mohl pomocí speciálně připraveného emailu spustit na serveru libovolný příkaz. Stejně, jak je popsáno v článku Exploit PHP’s mail() to get remote code execution z roku 2014.

Ladislav Hagara | Komentářů: 1
8.12. 16:00 | Nová verze

Byla vydána verze 0.98 svobodného nelineárního video editoru Pitivi. Z novinek lze zmínit například přizpůsobitelné klávesové zkratky. Videoukázka práce s nejnovější verzí Pitivi na YouTube.

Ladislav Hagara | Komentářů: 1
8.12. 15:00 | Zajímavý software

Stop motion je technika animace, při níž je reálný objekt mezi jednotlivými snímky ručně upravován a posouván o malé úseky, tak aby po spojení vyvolala animace dojem spojitosti. Jaký software lze pro stop motion použít na Linuxu? Článek na OMG! Ubuntu! představuje Heron Animation. Ten bohužel podporuje pouze webové kamery. Podpora digitálních zrcadlovek je začleněna například v programu qStopMotion.

Ladislav Hagara | Komentářů: 5
Kolik máte dat ve svém domovském adresáři na svém primárním osobním počítači?
 (32%)
 (23%)
 (29%)
 (7%)
 (5%)
 (3%)
Celkem 809 hlasů
 Komentářů: 50, poslední 29.11. 15:50
Rozcestník
Reklama

Dotaz: Jak nejlépe zabránit přepisování dat při dvou UPDATEch

10.10.2014 20:29 fean
Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Přečteno: 1144×
Ahoj.

V jiném dotazu byl uveden příklad, kdy dojde k souběhu dvou updatů, které si navzájem přepíšou data.

Konkrétně jde o toto:
A/ SELECT id, name FROM t WHERE id = 8 AND name != "Pepa";
B/ SELECT id, name FROM t WHERE id = 8 AND name != "Pepa";
A/ UPDATE t SET name = "Pepa" WHERE id = 8;
B/ UPDATE t SET name = "Josef" WHERE id = 8;
Ve výsledku chceme, aby v tabulce byla uložena hodnota "Pepa", a ten "Josef" se zamítl. Zatímco normálně to prostě přepíše a nikdo se nic nedozví. A to není dobře.

Protože dotyčný tvrdil, že to lze řešit a jako příklad uvedl Wikipedii a Hibernate, zkusil jsem si o tom něco nastudovat. Třeba u Hibernate jsem našel, že si nějak kontroluje verzi dat, a při update kontroluje, zda ukládá do stejné verze. Vypadalo to zajímavě.

Existuje nějaký osvědčený způsob? Co by ste doporučili?

Odpovědi

10.10.2014 20:39 Filip Jirsák
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Přidáte sloupeček verze, v každém selectu načtete, v update dáte do podmínky i tu verzi a při updatu ji zvýšíte o jedničku. A pak musíte nastavit izolaci transakcí v databázi tak, aby různé transakce nemohly souběžně updatovat stejné záznamy, nebo používat zamykání řádků pomocí klauzule FOR UPDATE.
10.10.2014 22:22 tacoberu | skóre: 3
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Jsi si jist, že jsou potřeba ty transakce?
10.10.2014 23:54 Filip Jirsák
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Bez toho může dojít k tomu, že jedna transakce vyhodnotí podmínky, pak se provede celá druhá transakce (provede se update), a následně se dokončí první transakce (provede se její update). Záleží ale na tom, co jednotlivé úrovně izolace transakcí zajišťují o té které konkrétní databáze. Ty transakce potřeba nejsou, můžete také spoléhat na to, že k souběžným transakcím, které budou aktualizovat stejné záznamy, nebude docházet moc často - pokud vám nevadí, že takový souběžný update, pokud už k němu dojde, přepíše předchozí data. Třeba pokud uživatelé editují záznam o osobě, vidí celý záznam osoby a jeden uživatel změní datum narození a druhý adresu, a náhodou by došlo souběžnému provedení updatů, můžete prohlásit, že je to chyba uživatele, protože viděl kompletní záznam a takto kompletní jej nechal uložit. Ale nechtěl bych, aby tímhle způsobem moje banka evidovala zůstatek na mém účtu, a pokud by přišly dvě příchozí platby najednou, jedna částka by se k zůstatku na účtu nepřičetla.
11.10.2014 00:05 Kit | skóre: 37 | Brno
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Je možné docílit téhož i bez transakce tak, že při optimistický zámek vložím přímo do updatu.
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
11.10.2014 00:40 tacoberu | skóre: 3
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
To vypadá jak?
11.10.2014 08:44 Kit | skóre: 37 | Brno
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Google dnes nefunguje? :-)

Optimistický zámek nemusí vypadat jako zámek. Při UPDATE do WHERE přidáš podmínku, která otestuje, zda je v přepisovaném poli původní hodnota. Pokud není, UPDATE se neprovede. Aplikace pak z počtu ovlivněných řádků pozná kolizi a pomocí třístranného porovnání může rozhodnout následující reakci.
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
11.10.2014 09:55 Filip Jirsák
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Jenom bych doplnil, že to ale funguje jenom tehdy, pokud jsou takhle chráněny všechny updaty v dané tabulce. Tj. nelze třeba udělat dávkový update, kde v podmínce nebudou verze:
UPDATE platy SET plat = plat * 1.1, verze = verze + 1 WHERE oddeleni = 1
11.10.2014 10:32 Kit | skóre: 37 | Brno
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Optimistické zamykání se uplatní spíš v situacích, kdy aplikace dlouho čeká na uživatelský vstup. Například pokud se dva redaktoři současně rozhodnou editovat jeden článek nebo dva úředníci modifikovat záznam o stejné osobě. Na hromadné změny se nehodí.

Místo (podle mne nebezpečného) číslování verzí raději volím timestamp.
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
11.10.2014 15:11 tacoberu | skóre: 3
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Místo (podle mne nebezpečného) číslování verzí raději volím timestamp.
Vidiš to. A já bych za nebezpečné považoval spíše ten timestamp. (Už se mi stalo, že v daném okamžiku se vygenerovali stejné konfliktní timestampy.)
11.10.2014 15:30 Kit | skóre: 37 | Brno
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Že byl stejný timestamp i data? V tom případě to přece nevadí, protože se to přepíše správně. V podstatě jsou timestamp i číslování verzí zbytečné, pokud porovnáváš data.
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
Josef Kufner avatar 11.10.2014 16:04 Josef Kufner | skóre: 66
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Na číslo verze potřebuješ rostoucí posloupnost, timestamp je neklesající posloupnost. Celkem běžně můžeš získat několik timestampů se stejnou hodnotou. Jakmile se ti tohle stane, bude se to chovat všelijak a výhody verzování okamžitě ztrácíš. A pokud se ti o aplikaci začnou přetahovat dva programy, např. importovací scripty, máš zaděláno na průser, neboť ty zvládnou vygenerovat požadavků se stejným timestampem pěknou hromadu.
Hello world ! Segmentation fault (core dumped)
11.10.2014 16:06 Kit | skóre: 37 | Brno
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Na importovací skripty se používá pesimistické zamykání, ne?
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
15.10.2014 11:50 logik
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Porovnávat data ale vždy možné není - např. pokud máš v db uloženy nějaké multimediální data, tak těžko budeš kvůli novému popisu videa porovnávat celé video....
15.10.2014 11:56 Kit | skóre: 37 | Brno
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Pokud mám v db multimediální data, mám je v samostatné tabulce. Jako ID pak používám SHA1 těchto multimediálních dat. Porovnání těch pár bajtů mi pak nečiní problém.
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
15.10.2014 12:36 logik
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Jo, to je rozumný - velká data jsou ale víc než jen multimédia a navíc člověk by rád měl nějaké "univerzální řešení", které jde integrovat do frameworku, by to nemusel furt psát. Z tohodle pohledu mi porovnávání podle verze přijde jako asi nejrozumnější kompromis cena/výkon/univerzálnost/pracnost.

Navíc porovnávání dat - tam je otázka: provnáváš-li všechna data, je výsledek stejný, jako když porovnáváš verzi (pominu-li updaty nedělající změnu). Porovnáváš-li pouze změněná data, tak to neni fail-proof: např. nevarovat při změně čísla popisného v adrese, když kolega vedle právě změnil ulici, asi není nejlepší nápad.... Takže porovnávání dat se buď musí psát "na míru", nebo nepřináší nic moc navíc oproti číslu verze, ta je ale na výkon nenáročná a univerzální.
15.10.2014 14:37 Kit | skóre: 37 | Brno
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Univerzální řešení neexistuje.

Multimédia často zabírají hodně místa a přesto jsou považována za atomická. Dalšími velkými daty bývají dokumenty, které se často kvůli indexování rozbíjí na atomy.

Číslo popisné a ulice bývají v jedné tabulce, obvykle tedy není problém porovnávat celý záznam - všechny sloupce adresy.
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
15.10.2014 16:19 logik
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
"Číslo popisné a ulice bývají v jedné tabulce, obvykle tedy není problém porovnávat celý záznam - všechny sloupce adresy."

To není problém - ale úplně stejnou funkci mi udělá porovnávání čísla verze - a tam se nemusím starat o to, zdali náhodou není nějaký sloupec v tabulce příliš velký apod. Takže moc nevidím důvod, proč to nedělat pomocí čísla verze. Možná to není univerzální, ale rozhodně to je univerzálnější a přitom na výkon méně náročné řešení.

11.10.2014 00:39 tacoberu | skóre: 3
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Ne, nebavíme so o situaci, kdy nám to nevadí :-)

Jen si nedovedu představit že by se někdo byl schopen trefit dovnitř takovéhoto příkazu:
UPDATE t 
SET name = "Pepa", version=version+1
WHERE id = 8 AND version=1;
ale to je možná jen má neznalost, a záleží, zda je to takto pro tu kterou databázi atomický příkaz.

Až po odeslání toho dotazu jsem si uvědomil, že teprve v případě vícero příkazů v jedné transakci to začne být sranda.

Takže beru zpět.
11.10.2014 10:36 Filip Jirsák
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Pokud by se takhle jednoduchý UPDATE neprovedl atomicky, byla by ta databáze opravdu divná. Jenže v tom UPDATE mohou být subselecty nebo volání funkcí, a to pak už záleží na konkrétní databázi, co zaručuje. Ale pokud se s tou databází pracuje např. jen přes ORM, všechny updaty mají v podmínce i rovnost verze a nastavují se v nich jen předem zadané hodnoty (tj. žádné SELECTy nebo volání funkcí v rámci updatu), pak to bude stačit.
13.10.2014 09:03 Michal Kubeček | skóre: 71 | Luštěnice
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Pokud by se takhle jednoduchý UPDATE neprovedl atomicky, byla by ta databáze opravdu divná.

Proč by měla být divná? Pokud chci atomicitu, mám prostředek, jak ji zajistit (transakce). Pokud ho nepoužiju, pak ji zajištěnou nemám; spoléhat na to, že ten či onen dotaz je tak jednoduchý, že prostě musí být atomický, je holý nesmysl.

Obecně mne nepřestává fascinovat, jak krkolomné konstrukce jsou lidé schopni vymyslet, aby se nemuseli naučit používat transakce.

13.10.2014 10:23 Filip Jirsák
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Transakce zajišťuje atomicitu celé transakce (buď se provede celá transakce, nebo nic), ale s atomicitou jednotlivých příkazů to nemá vůbec nic společného. Atomicita transakce neříká vůbec nic o tom, jestli version ve výrazu version + 1 bude mít stejnou hodnotu, jako version v podmínce WHERE, ani nic o tom, že v okamžiku zápisu té hodnoty version bude mít kteroukoli z předchozích dvou hodnot.
BEGIN
  UPDATE table SET version = version + 1 WHERE version = 1 AND id = 1;
  -- version == 1, podmínka WHERE splněna
                                                                           BEGIN
                                                                             UPDATE table SET version = 2 WHERE id = 1;
                                                                           COMMIT;
  -- version == 2, hodnota version + 1 je 3
                                                                           BEGIN
                                                                             UPDATE table SET version = 4 WHERE id = 1;
                                                                           COMMIT;
  -- version == 4
COMMIT;
-- version přepsáno ze 4 na 3
Tohle je atomická transakce, přesto se v průběhu UPDATE dvakrát změnila hodnota version.
13.10.2014 10:43 Michal Kubeček | skóre: 71 | Luštěnice
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Jestli jsem dobře pochopil, co má ten obrázek znamenat, tak něco takového vám má šanci projít nanejvýš tak s dirty read, což je úroveň, u které jsou oprávněné pochybnosti, jestli se vůbec ještě dá mluvit o transakcích, a kterou některé databáze ani nenabízejí.
13.10.2014 11:25 Filip Jirsák
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Může to nastat i u READ COMMITTED. Nejpodstatnější je ta změna před zápisem, a k té může dojít ve všech případech mimo SERIALIZABLE. V případě toho zápisu záleží především na tom, jak je udělané zamykání, a o tom transakce nic neříkají (respektive jediná úroveň, která v tomto smyslu něco zaručuje, je SERIALIZABLE). Podstatné je to, že úplné oddělení transakcí zajišťuje jen úroveň SERIALIZABLE, a že nižší úrovně nezajišťují vše, co lidé od transakcí intuitivně očekávají. Ale ne všude se SERIALIZABLE používá, takže pak je potřeba zjišťovat, co mi zvolená úroveň oddělení transakcí doopravdy zajišťuje, resp. jestli daný požadavek zajišťuje např. způsob implementace zamykání v dané databázi.
15.10.2014 11:56 logik
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
V tomdle máš sice na jednu stranu pravda, na druhou stranu pokud Ti jde o konzistenci dat, tak nikdo rozumný nepoužívá izolaci nižší než Repeatable read. Read uncommited snad nepoužívá nikdo a read commited má smysl používat jen u dat, u kterých Ti na nějaké chybě nesejde.

Protože když chceš validní data, tak tak či tak budeš muset zjistit, zdali repeatable read platí - a pak není důvod, proč to nenechat na DB, která to udělá 100% dobře a daleko rychleji, než uživatelský skript.
15.10.2014 12:11 Filip Jirsák
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Repeatable read zajistí, že version bude v té transakci stále stejné. Ale pořád to neřeší problém, že je potřeba aktualizovaná data zamknout. V případě aktualizace jednoho nezávislého řádku tabulky se o ten zámek postará databáze (ale je to záležitost konkrétní implementace, repeatable read transakce nic takového nevyžaduje). Jenže pokud ten update bude záviset na dalších datech, databáze o tom nemusí vědět, nezamkne vše potřebné a stále může dojít k tomu nechtěnému přepisu dat. Repeatable read přitom situaci paradoxně zhoršuje, protože zvyšuje pravděpodobnost, že se bude pracovat se starými daty.
15.10.2014 13:06 logik
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
1) Definice repeatable reads se liší (jinak ji definuje standard, jinak každá databáze), ale je poměrně široká shoda, že zámek nebo jiný mechanismus zajišťující totéž požaduje, neboť zakazuje změnu hodnoty prvku v databázi, který je přečten nějakou transakcí. Např. http://arxiv.org/pdf/cs.DB/0701157.pdf

2) Pokud update záleží na dalších datech, tak je stejně jako u těchto dat musím podmínit verzí těch dat. Pak to databáze zamkne readlockem, čili ta data nikdo pod rukama nezmění.
15.10.2014 13:22 Filip Jirsák
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Pokud zámek brání změně prvku přečteného jinou transakcí, je to už úroveň izolace transakcí serializable, ne?
15.10.2014 16:26 logik
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
To teda rozhodně není. Serializable je úroveň, která oproti repeatable reads navíc zabraňuje tzn. phantom reads. To je případ, kdy stejný select vrátí dvakrát jiný rozsah záznamů, protože mezi tím nějaké záznamy přibyly.

Proto serializable - kdyby transakce běželi jedna za druhou, tak se toto stát nemůže. Repeatable read zajišťuje pouze neměnnost záznamů, které přečtu, nikoli toho, co "nečtu, protože to tam ještě není". Proto repeatable read - záznam co jednou přečtu, tak přečtu při každém následujícím čtení stejně.

Phantom reads se nelze vyhnout zamykáním jednotlivých záznamů, ale pouze range-lockem , popř. nějakou verzí snapshotové architektury, kdy nové záznamy nejsou pro starší transakci vidět.
15.10.2014 19:47 Filip Jirsák
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Aha, já to bral podle PostgreSQL, kde repeatable read znamená, že se čtou data (ne jen přečtené záznamy, ale vše) ve stavu, v jakém byla na začátku transakce - takže phantom reads nemůžou nastat. Nenapadlo mne, že standard má v tomhle mírnější požadavky. Jak jsem psal, vždycky je potřeba si zjistit, co přesně která databáze zaručuje...
20.10.2014 12:33 logik
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
To sice jo, ale ani "snapshot isolation", kterej používá postgresql od verze 9.1 pro úroveň repeatable read nedává jistotu serializovatelného rozvrhu transakcí. PostgreSQL má striktnější nároky na jednotlivé úrovně, ale ani v ní neplatí, že repeatable read a serialization je stejná úroveň.

Pro zajištění verzování Ti pak stačí repeatable read za předpokladu, že do všech záznamů, co na nich závisí validita Tvých dat a není zajištěna constrainy, zapisuješ, nebo serializable pokud nezapisuješ.

Serializable potřebuješ pouze pokud data závisí na dvou různých záznamech a Ty měníš pouze jeden (a to ještě pouze u "snapshot" architektury, u zámků ani toto nemůže nastat). V tu chvíli ale z definice verzování Ty dva spojené záznamy jsou defakto jedním logickým záznamem a verzovat by se měli "spolu".

Již repeatable read Ti zajišťuje, že se data nezmění mezi Tvým čtením a zápisem i v ANSI SQL normě, natož v striktnější postgresql, která má na tuto úroveň striktnější nároky. K prevenci změny dat před zápisem prostě Serializable třeba není ani ve významu ANSI ani postgres.
rADOn avatar 13.10.2014 14:49 rADOn | skóre: 44 | blog: bloK | Praha
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Pokud databáze umí transakce (tj. není to MyISAM) a řádek je zamčený FOR UPDATE tak žádné verzování není potřeba. A pokaždý když takhle vyprasíš standartní vlastnosti databází ježíšek zabije koťátko…
"2^24 comments ought to be enough for anyone" -- CmdrTaco
13.10.2014 15:31 Filip Jirsák
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Pokud SELECTem vybírám data, která zobrazím na webu uživateli a on nad tím bude pár hodin dumat, než něco upraví, asi nechci mít celou dobu otevřenou transakci a zamčený řádek v tabulce.
rADOn avatar 13.10.2014 16:22 rADOn | skóre: 44 | blog: bloK | Praha
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Jasně že ne. Transakci chceš mít otevřenou jen tak dlouho abys zjistil jestli se ti nezměnila data pod rukama. Na to verzování nepotřebuješ. Na prostý souběh dvou updatů na který se ptal OP to už vůbec nepotřebuješ.
"2^24 comments ought to be enough for anyone" -- CmdrTaco
Josef Kufner avatar 13.10.2014 16:34 Josef Kufner | skóre: 66
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
To mi tak připomíná etag.
Hello world ! Segmentation fault (core dumped)
13.10.2014 16:41 Filip Jirsák
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Verzování nepotřebuju, ale je jednodušší porovnat jedno číslo verze, než porovnávat celý záznam. V příkladu uvedeném v dotazu UPDATE B přepíše změny, které provedl UPDATE A. Tazatel se ptal, jak tomu skrytému přepsání změn předejít.
10.10.2014 21:29 tacoberu | skóre: 3
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Jak píše @Filip Jirsák:
UPDATE t 
SET name = "Pepa", version=version+1
WHERE id = 8 AND version=1;
Ale musíš si odchytit, zda se ten dotaz provedl či ne.

Případně je možnost si na to napsat assertovací funkci. Něco jako:
UPDATE t 
SET name = "Pepa", version=assert_version(version, 1)
WHERE id = 8;
Ale to je fakt jen taková vychytávka, aby se ti jednotně vraceli výjimky.
10.10.2014 21:56 Kit | skóre: 37 | Brno
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Většinou se řeší případ, aby dva uživatelé nemodifikovali stejný záznam. Jedna modifikace by v tichosti modifikovala výsledek té druhé a uživatel by se o tom nedozvěděl. Obvykle se to řeší buď optimistickým, anebo pesimistickým zamykáním. Každý z nich má své výhody a nevýhody v různých případech užití.
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
AraxoN avatar 11.10.2014 11:57 AraxoN | skóre: 45 | blog: slon_v_porcelane | Košice
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Ak ide o automatizované spracovanie, tak na to je ideálny row-level locking (SELECT ... FOR UPDATE).

Ak ide o údaje vkladané používateľom, kde sa medzi SELECT a UPDATE čaká na akciu používateľa, tak mne sa osvedčilo ku často meneným tabuľkám pridať log so zmenami, ktorý sa zobrazuje pri danom zázname, napr. 2014-10-11 11:47:35 John Doe changed 'name' from 'Ludvig' to 'Pepa', 2014-10-11 11:47:59 Jane Roe changed 'name' from 'Pepa' to 'Jozef'. Tak sa dá dopátrať k pôvodnému zneniu, ako aj k tomu, čo sa stalo, kedy a prečo.

Vidím jeden problém s verziovaním, ktoré tu navrhujú kolegovia. Keď druhý UPDATE neprebehne, tak čo potom spraví používateľ? Otvorí si aktuálny záznam a začne svoje zmeny písať znova? Čo keď robí zložitejšie zmeny a kým ich dokončí tak mu to zase niekto updatne? Alebo čo keď bol so zákazníkom na telefóne, zmeny mu zákazník diktoval a sám si ich nepamätá?
A fine is a tax for doing wrong. A tax is a fine for doing well.
11.10.2014 12:30 Kit | skóre: 37 | Brno
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Pokud se změny neprovedou, aplikace si stále pamatuje vstup od uživatele a původní hodnotu. K tomu dalším dotazem získá novou hodnotu z databáze. Může provést třístranné porovnání, jehož interpretace záleží na případu užití. Jiné to bude v případě atomických hodnot a jiné v případě editace článku. Také může uživateli nabídnou všechny tři varianty, ať si z nich vybere nebo ať udělá nějaký merge.
Komentáře označují místa, kde programátor udělal chybu nebo něco nedodělal.
11.10.2014 15:13 tacoberu | skóre: 3
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Vidím jeden problém s verziovaním, ktoré tu navrhujú kolegovia. Keď druhý UPDATE neprebehne, tak čo potom spraví používateľ? Otvorí si aktuálny záznam a začne svoje zmeny písať znova? Čo keď robí zložitejšie zmeny a kým ich dokončí tak mu to zase niekto updatne? Alebo čo keď bol so zákazníkom na telefóne, zmeny mu zákazník diktoval a sám si ich nepamätá?
Mrkni jak to dělá Wikipedia. Minimálně pro ilustraci.
AraxoN avatar 11.10.2014 16:32 AraxoN | skóre: 45 | blog: slon_v_porcelane | Košice
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Wikipediu poznám, používam, editujem. Funguje to výborne na články, resp. na dlhé texty. Je to jeden jediný dátový typ, ktorý tam musia riešiť a riešia ho dobre. Už ťažšie si viem predstaviť rôzne štruktúrované dáta, ktoré sú potrebné v bežnom CRM. Objekt "Zákazník" nie je jeden dlhý text, ale je rozsekaný na jednotlivé políčka - meno, priezvisko, ulica, mesto, atď. a počet políčok sa časom zvykne len zvyšovať. Urobiť k objektu logovanie zmien a výpis z logu je záležitosť na pol hodiny programovania. Urobiť a udržiavať formulár na merge to už je robota na deň alebo viac (podľa toho, aký framework sa v danom systéme používa). Nehovoriac o tom, že po naprogramovaní merge musí nasledovať preškolenie obsluhy, lebo prvá reakcia bežnej tety pri zobrazení niečoho nového je kliknúť čo najrýchlejšie OK, alebo Storno, čím dôjde k tichému prepísaniu, alebo zahodeniu zmien - a to v žiadnom prípade nie je správny postup.
A fine is a tax for doing wrong. A tax is a fine for doing well.
12.10.2014 02:41 tacoberu | skóre: 3
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Mě přijde naopak více menších políček jednodužší. Zobrazím diff pro každou položku mající konflikt (a jen pro tu), barevně zvýrazním. Pokud si toho nevšimne, tak už to dělá naschvál.

Samozřejmě se dá přidělat verzování změn, plus logování konfliktů pro ověření nějakou třetí osobou. Ale to se imho dostáváme trochu mimo původní technické zaměření, jak řešit konflikt.
12.10.2014 22:52 Filip Jirsák
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Tohle je problém toho, že se dnes do relačních databází obvykle ukládají "objekty" nebo struktury - vezme se formulář od uživatele, kde jsou částečně původní data a částečně uživatelem změněná, a vše se to znovu zapíše do databáze. Přitom to většinou není to, co uživatel chce - uživatel chce třeba změnit jméno nebo adresu. Přitom SQL umí updatovat jenom jednu nebo několik položek záznamu. Kdyby aplikace umožnila uživateli provést tu změnu, kterou chce, docházelo by ke konfliktům výrazně méně. A každý takový konflikt by znamenal chybu v procesech nebo na straně uživatele - k té změně od uživatele musí vždy být nějaký podnět, a nemohou existovat dva různé platné podněty na změnu jména člověka ve stejný okamžik.
12.10.2014 23:54 tacoberu | skóre: 3
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Souhlasím.

Jak by sis představoval, že by to UI mělo vypadat? Okamžité uložení u každé změny políčka?
13.10.2014 08:29 Filip Jirsák
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Okamžité uložení určitě ne. Dá se to udělat třeba tak, že se změněná pole zvýrazní, a uživatel bude vědět, že se ukládají jen změněné údaje. Třeba může být zobrazení v needitovatelné formě, a teprve po kliknutí se políčko změní v editační (pak je ale ještě potřeba nějak vyřešit ovládání z klávesnice).
13.10.2014 11:23 Tomáš
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Když jsem programoval v PowerBuilderu, tak ten to dělal tak, že měl několik bufferů s daty.

1. buffer - natažená data z DB

2. buffer - data, co mění uživatel

Když se dělal update, tak to v principu fungovalo takto: update set (data z 2.bufferu) where (data z 1. bufferu)

Mezi těmi sloupci musel být i PK.

Když se updatoval jiný počet řádek, než než se chtělo updatovat, tak se v DB udělal rollback a uživatel uviděl hlášku "row change between retrieve and update"
15.10.2014 12:02 logik
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch
Ale toto přeci není problém DB. Vždyť můžeš detekovat, které políčka uživatel změnil, a udělat update pouze těch políček, co byly změněny a udělat update jen z nich.

To, že se dělá update všeho není vůbec problém SQL databáze - ta to umožňuje - ale problém formulářových frameworků, které nejsou zařízeny na detekci provedených změn.

Jediné, co v tom hraje proti databázi je to, že většina databází má zámky max. na úroveň řádků, ale pokud se bavíme o situaci, kdy jde o interaktivní zpracování, tak tam pesimisticky zamykat stejně nejde.
vlastikroot avatar 15.10.2014 22:40 vlastikroot | skóre: 24 | blog: vlastikovo | Milevsko
Rozbalit Rozbalit vše Re: Jak nejlépe zabránit přepisování dat při dvou UPDATEch

Co databazi poslu, to tam mam. Co vic bych od ni chtel? Atomicitu zarucim na urovni DB pomoci transakce, ale bez atomicity na urovni aplikace je to k nicemu.

Staci treba hlidat zmenu (verzovanim) a v pripade zmeny upozornit uzivatele, pripadne radky v tabulce zamykat.

Ja treba pro realtimovost aplikace pouzivam zvlastni sitovy synchronizacni server, ktery ohlasuje klientum, jaka sdilena data si maji nacist, pripadne co maji udelat. Tim se tomuhle aktivne vyhnu, presto kontroluji verzi dat.

Sg1-game | We will destroys the Christian's legion ... and the cross, will be inverted | IP 80.188.182.6

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.