Offline concurrency patterns Petr Smrček Ondřej Svoboda ČVUT FEL A7B36ASS – Architektura SW sytémů LS 2013
Offline concurrency patterns Problém systémové (databázové) transakce by měly být krátké business transakce mohou být velmi dlouhé Příklad: editace záznamu uživatel přečte z databáze záznam v editačním formuláři upravuje data data uloží, mezitím s nimi ale mohl pracovat někdo jiný Jak na to? je třeba řešit aplikační logikou – business transaction Způsoby řešení Optimistic offline lock Pessimistic offline lock Coarse-grained lock Implicit lock
Optimistic offline lock
Kdy použít kolize mezi transakcemi nejsou příliš očekávané nevadí, pokud transakce na konci spadne a práce bude ztracena Princip práce s daty je povolena všem pokud by mělo dojít ke konfliktu, transakce je neúspěšná (rollback) Implementace nejčastěji použitím verzí každá úprava daného záznamu inkrementuje jeho verzi konflikt nastane, pokud se má upravit záznam s vyšší verzí, než jakou měl při čtení implementace je jednoduchá
Optimistic offline lock – příklad
Optimistic offline lock – SQL implementace UPDATE Customer SET..., version = (session’s version + 1) WHERE id = 129 AND version = (session’s version)
Optimistic offline lock – aplikační implementace Customer c = customerDao.getCustomer(); /* do application logic */ Transaction::begin(); if (customerDao.checkVersion(c.version)) { c.save(); Transaction::commit(); } else { Transaction::rollback(); }
Optimistic offline lock – nekonzistentní čtení dat Nekonzistentní čtení dat kontrola verzí pouze při UPDATE nebo DELETE neřeší následující problém: v transakci používáme i data, která neměníme, ale výsledek transakce na nich závisí Umělá úprava dat nad těmito daty provedeme taktéž UPDATE, ale změníme pouze verzi + není třeba žádná další zamykací logika - zbytečný zápis, zbytečně označujeme pro ostatní transakce stejná data různou verzí Ruční kontrola verze pro tato data si pomatujeme původní verzi a zvlášť jí kontrolujeme + efektivní řešení - je třeba dát pozor na stupeň izolace systémových transakcí (je potřeba repeatable read či silnější), aby nám neprezentovaly stejnou verzi Coarse-grained lock
Optimistic offline lock – použití Verzovací systémy SVN, Git,... při konfliktu řeší uživatel JPA 2.0 int version; MediaWiki
Pessimistic offline lock
Pravděpodobnost konfliktu je velká preventivně zabránit vzniku konfliktu nejobvyklejší implementace – zamykání zdrojů business transakce musí získat zámek zdroje před tím, než se zdrojem začne pracovat Zamykání zdrojů Exclusive Write Lock – nikdo nesmí data číst, ani zapisovat Shared Read Lock Data jsou zamknuta pro čtení Více transakcí může číst, ale ne zapisovat kompatibilita zámků: SH × SH ano, SH × EX ne, EX × EX ne Řešení zamítnutí transakci zrušit počkat na zámek
Pessimistic offline lock
Pessimistic offline lock – Lock manager Lock manager udržuje v paměti seznam zamčených objektů pokud aplikace běží na clusteru serverů, musí být tento seznam uložen v databázi business transakce nemanipuluje se zámky přímo, ale pouze přes lock managera Práce lock managera kdy zamknout – dříve než začnu se zdroji pracovat jistota, že mám nejaktuálnější verzi zdroje co zamknout – typicky ID zdroje kdy odemknout – nejlépe na konci transakce co dělat když nelze získat zámek – nejjednodušší je transakci zrušit (rollback)
Pessimistic offline lock - Deadlock Deadlock transakce 1 drží lock na zdroj 1 a požaduje zámek na zdroj 2 transakce 2 drží lock na zdroj 2 a požaduje zámek na zdroj 1 protože obě transakce nemohou pokračovat dokud nebudou zdroje volné a obě transakce nemohou uvolnit zámky, vzniká deadlock Řešení nečekat na zámky zrušit transakci při prvním nedostupném zámku
Pessimistic offline lock – Lost transactions Lost transactions klientský proces spadne uprostřed transakce u webové aplikace typicky uživatel transakci nedokončí transakce neuvolnila zámky Řešení timeout na úrovni aplikace timeout na úrovni aplikačního serveru timeout http session po timeoutu se uvolní / invalidují zámky
Pessimistic offline lock - Použití Použití tam kde předpokládáme vznik konfliktů - nutnost řídit souběžné operace nebo uživatel nesmí přijít ani o část své práce rollback transakce nemusí být vždy možný Implementace JPA 2 public void updateBalance(String id, BigDecimal amount) { Account acc = (Account) sessionFactory.getCurrentSession().get(Account.class, id, LockMode.UPGRADE); acc.setBalance(acc.getBalance().subtract(amount)); save(acc); }
Coarse-grained lock Implicit lock
Coarse-grained lock zamykání skupin objektů jedním zámkem Výhody proti zamykání jednotlivých objektů Optimistické zamykání – pro zamčení (načtení verzí) je potřeba načíst velké množství objektů Pesimistické zamykání – rozsáhlá tabulka záznamů
Coarse-grained lock – optimistické zamykání Sdílený objekt verze
Coarse-grained lock – pesimistické zamykání Zamykání sdíleného objektu verze
Coarse-grained lock – pesimistické zamykání Zamykání kořene
Implicit lock Princip Někdo hlídá přístup k datům a zajišťuje automatické zamykání Eliminuje se tak spousta potenciálních chyb spojených s ručním hlídáním zámků
Offline concurrency patterns – shrnutí Co řeší? dlouhé transakce na úrovni aplikační logiky Možnosti implementace Optimistic offline lock – jednoduchá implementace, kolize nejsou moc očekávány Pessimistic offline lock – kolize očekávány, preventivní ochrana Coarse-grained lock – sjednocení více objektů pod jeden zámek Implicit lock – zámky řešeny automaticky např. frameworkem Související vzory Overly optimistic lock strategie spoléhající na to, že žádné kolize nenastanou Identity map zajišťuje, že každý objekt bude načten pouze jednou
Zdroje Martin Fowler - Catalog of Patterns of Enterprise Application Architecture ( Enterprise Architecture Patterns ( The Addison-Wesley Signature Series (