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.