Deadlock v databázi, který vznikl na úrovni requestu v komponentě

Kdyz budu mit komponentu se svou vlastni databazi, a databazi budu mit nastavenou v rezimu SERIALIZABLE, tak se muze stat, ze 2 Requesty se na urovni databaze navzajem zablokuji. Databaze sice umi detekovat deadlock 2 transakci a dokaze na jedne z nich udelat Rollback, nicmene co se nasledne stane s tim Requestem - to jako 1 z nich bude vzdycky neuspesny, ja obdrzim bug, a budu muset tento deadlock case to case "agilne" zafixovat?

A mimochodem, neznamena vlastne moznost takoveho deadlocku vlastne to, ze mam spatne strukturovana data a logiku manipulace s nimi a ze bych praveze mel izolaci SERIALIZABLE pouzit, protoze me bude na toto deadlocky upozornovat?
« Poslední změna: 22. 02. 2019, 09:48:07 od Petr Krčmář »


I v korektní aplikaci může dojít  v databázi k deadlockům - pokud k nim nedochází extrémně často, tak nejsou problém. Databáze deadlock dokáží identifikovat a řešit. Zrovna  u úrovně serializable by klient měl být napsán takovým způsobem, aby dokázal zopakovat poslední transakci - kromě jiného může chybu vrátit i COMMIT z důvodu nemožnosti serializace transakcí.

Ohledně designu platí doporučení, aby často referencované tabulky (na které se často odkazujete cizími klíči) neměly extrémně nestabilní položky (např. last_update atd). Pak samozřejmě klasika - pokud držím blokovací zámky (po modifikaci řádků), tak bych měl dokončit transakci co nejdříve. Pak klesá riziko souběhu a tudíž i riziko deadlocků.

Alternativou je pesimistické zamykání, případně používání klauzulí NOWAIT, případně SKIP_LOCKED a ošetřování si zámků vlastními silami. To určitě ale běžnému uživateli nedoporučuji.

Ještě jednou - není potřeba se bát deadlocků, pokud mám korektně napsanou aplikaci, a pokud jich není příliš. Pokud je jich příliš - stovky za hodinu a výš, tak něco je špatně - od použití špatné technologie, frameworku, db designu, těžko říct co - problém může být kdekoliv.

Alternativou je pesimistické zamykání, případně používání klauzulí NOWAIT, případně SKIP_LOCKED a ošetřování si zámků vlastními silami. To určitě ale běžnému uživateli nedoporučuji.

Já konkrétně NOWAIT naopak doporučuji, zjistil jsem, že pro začínající programátory je to lépe představitelná cesta, jak se naučit fungování lockování. Začínající programátoři v praxi moc často na problém s locky nenarazí (testovací data jsou malá, i souběh locků trvá milisekundy, ...). Na častou chybu, na kterou narážím je tendence programátorů volat script minutovým cronem (setkal jsem se i se sekundovým), kde už se bez NOWAIT pracovat nedá.

Alternativou je pesimistické zamykání, případně používání klauzulí NOWAIT, případně SKIP_LOCKED a ošetřování si zámků vlastními silami. To určitě ale běžnému uživateli nedoporučuji.

Já konkrétně NOWAIT naopak doporučuji, zjistil jsem, že pro začínající programátory je to lépe představitelná cesta, jak se naučit fungování lockování. Začínající programátoři v praxi moc často na problém s locky nenarazí (testovací data jsou malá, i souběh locků trvá milisekundy, ...). Na častou chybu, na kterou narážím je tendence programátorů volat script minutovým cronem (setkal jsem se i se sekundovým), kde už se bez NOWAIT pracovat nedá.

No tím, že vyblokuji jakékoliv čekání na zámek se toho moc nenaučím  :). Hodně záleží na kontextu, použité databázi, izolačním levelu, atd. Osobně bych určitě NOWAIT nedoporučil genericky používat - ale beru, že neznám prostředí, technologie, které používáte. V Postgresu jde případně nastavit lock wait timeout.

No tím, že vyblokuji jakékoliv čekání na zámek se toho moc nenaučím  :). Hodně záleží na kontextu, použité databázi, izolačním levelu, atd. Osobně bych určitě NOWAIT nedoporučil genericky používat - ale beru, že neznám prostředí, technologie, které používáte. V Postgresu jde případně nastavit lock wait timeout.

Ano, vím. Mluvím o tom, že naopak přes NOWAIT se mi lépe učí nováčci. Nevím, jakou zkušenost máte Vy, ale ke mně se dostávají "SQL" programátoři, kteří umějí udělat jeden select v MySQL, vlastnosti transakcí neznají a lock je pro ně něco, co v životě neslyšeli a nechápou ani význam. Prostě taková schola ludus v Postgresu.


No tím, že vyblokuji jakékoliv čekání na zámek se toho moc nenaučím  :). Hodně záleží na kontextu, použité databázi, izolačním levelu, atd. Osobně bych určitě NOWAIT nedoporučil genericky používat - ale beru, že neznám prostředí, technologie, které používáte. V Postgresu jde případně nastavit lock wait timeout.

Ano, vím. Mluvím o tom, že naopak přes NOWAIT se mi lépe učí nováčci. Nevím, jakou zkušenost máte Vy, ale ke mně se dostávají "SQL" programátoři, kteří umějí udělat jeden select v MySQL, vlastnosti transakcí neznají a lock je pro ně něco, co v životě neslyšeli a nechápou ani význam. Prostě taková schola ludus v Postgresu.

Popravdě řečeno, s tímhle levelem programátorů se moc nepotkávám. U běžných uživatelů, kteří primárně řeší reporty tyto znalosti nečekám, a databáze tím, že řeší konzistenci a izolaci, je odstíní od detailů. U aplikačních programátorů naopak předpokládám, že znají základy - race condition, izolační levely, atd. pokud chtějí dělat s db. Pokud ne, tak je to pak těžké.

Re:Deadlock v databázi, který vznikl na úrovni requestu v komponentě
« Odpověď #6 kdy: 22. 02. 2019, 17:24:01 »
Jasne, ono ten deadlock jde vlastne snadno vyresit na urovni frameworku, ze pokud DB vratila nejaky deadlock error, tak se muze znova automaticky zopakovat request. Jenze co treba Spring Framework, automaticky pochybuju ze to dela.

Re:Deadlock v databázi, který vznikl na úrovni requestu v komponentě
« Odpověď #7 kdy: 25. 02. 2019, 07:26:04 »
Zopakovat request – to není tak jednoduché. Nestačí zopakovat request, je potřeba začít znovu celou transakci. Některé requesty se mohou tvořit podle výsledků předchozích requestů, pak slepé opakování requestů nedává smysl…

Framework by to mohl zkusit zopakovat, pokud bude mít třeba callback, který udělá celou transakci. Takový callback by neměl mít side effecty* mimo tu databázi, jinak se mohou dít podivné věci, jako třeba několikrát odeslaný e-mail.

*) Je potřeba se na to dívat při rozumné úrovni abstrakce – možná třeba logování zde nemusíme brát jako side effect.