Autor Téma: deadlock při více pristupech  (Přečteno 4711 krát)

Offline Sat1

  • Nováček
  • *
  • Příspěvků: 19
  • Karma: 0
deadlock při více pristupech
« kdy: 10-04-2014, 21:21:45 »
Dobrý den, prosím o radu. Mám udělanou jednoduchou aplikaci pracujici s firebirdem. V aplikaci data z tabulky čtu, upravuji i zapisuji, vše je ok dokud se nespustí tato aplikace na druhém počítači. Pak čas od času nastane chyba
Kód: [Vybrat]
deadlock
update conflicts with concurrent update
je mi jasné že to nastane když je obě aplikace pokouší zapisovat najednou, ale jal se to dá ošetřit? Omlouvám se za chyby, Píšu z mobilu.

Offline Mi.Chal.

  • Guru
  • *****
  • Příspěvků: 574
  • Karma: 25
Re:deadlock při více pristupech
« Odpověď #1 kdy: 10-04-2014, 21:33:54 »
To je normální v případě, že víc transakcí mění společná data (typicky víceuživatelské systémy) a aplikace s tím musí počítat. Existují dva způsoby, pesimistický (předpokládáš, že konflikt bude nastávat často) a optimistický (spíš nenastane). V prvním případě se dají použít třeba zámky, takže editovat půjde jenom jednomu uživateli. Blbé je, že otevřením záznamu může blokovat ostatní, protože budou čekat dokud změny neuloží. Ve druhém se pokusíš uložit změny a pokud to neprojde z důvodu konfliktu, tak podle situace můžeš zkusit udělat celou transakci znovu nebo pokud je to uživatel, tak mu můžeš napsat, že data někdo změnil, načíst znovu a pokusit se udělat nové změny a uložit.

Offline Sat1

  • Nováček
  • *
  • Příspěvků: 19
  • Karma: 0
Re:deadlock při více pristupech
« Odpověď #2 kdy: 10-04-2014, 21:57:49 »
Díky, bylo by možné poslat odkaz kde čerpat informace, hlavně k té druhé variantě, ale rád se přiučím i té první.

Offline Mi.Chal.

  • Guru
  • *****
  • Příspěvků: 574
  • Karma: 25
Re:deadlock při více pristupech
« Odpověď #3 kdy: 10-04-2014, 22:47:48 »
Takhle z hlavy nic konkrétního nevím, našel jsem třeba http://javicka.blogspot.cz/2008/03/konkurenn-pstup-k-datm-zamykac.html.

Offline Mi.Chal.

  • Guru
  • *****
  • Příspěvků: 574
  • Karma: 25
Re:deadlock při více pristupech
« Odpověď #4 kdy: 10-04-2014, 22:57:04 »
Tady máš ještě něco víc teoretického http://eamos.pf.jcu.cz/amos/kat_inf/externi/kat_inf_65590/files/studijni_texty/dbs10_transakce.pdf, isolation levely ve FB http://www.firebirdsql.org/manual/isql-transactions.html

Offline Sat1

  • Nováček
  • *
  • Příspěvků: 19
  • Karma: 0
Re:deadlock při více pristupech
« Odpověď #5 kdy: 10-04-2014, 23:06:20 »
Děkuji, prostuduji. Nejhorší je, že na takovéto problémy jsem narazil až za provozu a samozřejmě, že osoby stím pracující to chtějí opravené hned.

Offline Mi.Chal.

  • Guru
  • *****
  • Příspěvků: 574
  • Karma: 25
Re:deadlock při více pristupech
« Odpověď #6 kdy: 10-04-2014, 23:46:37 »
Tak člověk by měl nějakou teorii znát, jinak s tím vždycky dřív nebo později narazí. To je jako nedělat synchronizace ve vícevláknových aplikacích, to taky může vypadat funkční, ale je to časovaná bomba :-).

Offline Sat1

  • Nováček
  • *
  • Příspěvků: 19
  • Karma: 0
Re:deadlock při více pristupech
« Odpověď #7 kdy: 12-04-2014, 10:40:38 »
Ano jsem se k tomu dostal tak trochu nahodou, zakaznik potreboval udelat evidencni skladovy SW a ja jsem nejak neodolal teto vyzve. Naposledy jsem programoval na skole v asembleru, takze OOP jsem videl poprve a zacal se ho tim ucit.
Procetl jsem ty odkazy, sice jiz vim jak to funguje, ale nemam nejmensi poneti jak ty zamky pouzit. Asi nejprijatelnejsi verze se zda pesimisticka online verze zamikani. Jak to ale pouzit v praxi?

Offline Mi.Chal.

  • Guru
  • *****
  • Příspěvků: 574
  • Karma: 25
Re:deadlock při více pristupech
« Odpověď #8 kdy: 12-04-2014, 11:14:25 »
Ten pesimistický se asi moc nepoužívá a implementace záleží i na použité db, pro FB viz třeba http://www.firebirdsql.org/refdocs/langrefupd21-notes-withlock.html.

V praxi se to dělá spíš tím optimistickým způsobem. Třeba ORM typu hibernate to řeší tak, že k tabulkám přidávají sloupec version a do DML příkazů (update, delete) se přidává podmínka na verzi, např. Update table set name = @name where id = @id and version = @version, kde @version je verze přečtená při načtení přes select. Pokud data někdo mezitím změnil, tak update nic nezmění (nebude sedět verze), což musíš zkontrolovat - ty metody typu Execute vrací počet změněných řádků, takže tam bude 0.

Ověř si ještě jak se to bude chovat u tvé db podle isolation levelu transakce - třeba MSSQL s read committed čeká, dokud nedoběhne jiná transakce měnící data, která chceš načíst selectem. U Oraclu a FB to zase vracelo původní data, tam se myslím muselo dát select for update. Já jsem dělal s MSSQL, takže u ostatních ti moc neporadím.

Offline Sat1

  • Nováček
  • *
  • Příspěvků: 19
  • Karma: 0
Re:deadlock při více pristupech
« Odpověď #9 kdy: 12-04-2014, 12:24:45 »
Takto to zní pochopitelne, ale ošetřit to případ kdy jeden uživatel spustí update na 30t záznamu a v průběhu spustí druhý uživatel update jednoho z posledních záznamů kam první update ještě nedorazil? Nenastane pak opět deadlock? Nebo druhá transakce bude čekat na ukončení první bez vyvolání chyby?

Offline Mi.Chal.

  • Guru
  • *****
  • Příspěvků: 574
  • Karma: 25
Re:deadlock při více pristupech
« Odpověď #10 kdy: 12-04-2014, 12:48:11 »
Tak záleží jak to updatuješ, jestli záznam po záznamu nebo hromadnou where podmínkou. Pokud se to mění hromadně, tak by to zásadně vadit nemělo, druhý update by měl počkat, než dojede ten hromadný (ale asi budeš muset poladit ty locky a transaction isolation level). Ještě jsem narazil na nějaký document k FB - https://www.ibphoenix.com/resources/documents/design/doc_22

Offline Sat1

  • Nováček
  • *
  • Příspěvků: 19
  • Karma: 0
Re:deadlock při více pristupech
« Odpověď #11 kdy: 12-04-2014, 14:33:33 »
Update delam hromadne. Ono ta chyba nastava asi vzdy v jednom okamziku a to pri ukonceni aplikace, kdy se provadi
Kód: [Vybrat]
UPDATE EVIDENCE_MATERIALU SET TISK = 0 , coz je aktualne pro cca 30t zaznamu. Tento sloupec pouzivam pro urceni ktere zaznamy se maji tisknout, protoze me jiny zpusob v momente kdy jsem to tvoril nenapadl. Je-li hodnota 1, tak se zaznam tiskne pres fastreport kde je prozmenu
Kód: [Vybrat]
SELECT * FROM EVIDENCE_MATERIALU WHERE TISK=1. Je to hrozne nesiknovne reseni, protoze si navzajem uzivatele mohou menit co se ma zrovna tisknout, ale fungovalo to naprosto spolehlive dokud s aplikaci pracoval jen jeden clovek, pozadavek na vicero uzivatelu prisel az zahy. Takze od teto metody budu muset stejne upustit, ale chtel jsem to osetrit, nez vymyslim neco jineho. Zacal jsem kvuli tomu pouzivat smdbgrid a chci tam udelat zatrhavatka ve virtualnim sloupci, ale zatim trochu patram jak na to. Navic premyslim o migraci z FB na MSSQL, kvuli absenci boolean typu a dalsimu checkbox sloupci v gridu. Sice jsem nasel nejake navody jak to obejit pomoci vlastni domeny, ale smdbgrid mi to stejne jako boolean nebral.

Offline Stanislav Hruška

  • Padawan
  • ******
  • Příspěvků: 4426
  • Karma: 39
    • Verze Delphi: XE7 professional
Re:deadlock při více pristupech
« Odpověď #12 kdy: 12-04-2014, 14:46:45 »
Nepoznám smdbgrid (používamVirtualStringTree), ale niekde si musíš zistiť hodnotu poľa a poslať smdbgrid typ boolean.
Delphi XE7, FireBird
Expert na kladenie nejasne formulovaných otázok.

Offline Mi.Chal.

  • Guru
  • *****
  • Příspěvků: 574
  • Karma: 25
Re:deadlock při více pristupech
« Odpověď #13 kdy: 12-04-2014, 18:34:07 »
Samotný Update se Select ti deadlock snad neudělá, buď vrátí stará data nebo počká. Co má ten tvůj update tisku vůbec řešit? Vypadá to jako nějaká blbost :-) a navíc si uživatelé budou data ovlivňovat navzájem.

Offline Sat1

  • Nováček
  • *
  • Příspěvků: 19
  • Karma: 0
Re:deadlock při více pristupech
« Odpověď #14 kdy: 12-04-2014, 21:26:21 »
Ano, ovlivnuji si to navzajem. Dneska jsem si k tomu ale sednul a cele to predelal, takze ten update tisku je uz vypusten a resim to checkboxem v gridu. Kazdopadne diky, zase jsem o neco chytrejsi. Ted uz jen donutit grid, aby bral smallint o hodnotach 0 a 1 jako boolean je to dle predstav.