Lige siden fremkomsten af DB2 har vi kæmpet mod deadlocks og timeouts. Et væsentligt skridt i den rigtige retning blev taget med indførelsen af TYPE 2 indexes i version 4. Der er dog stadig mange situationer, hvor der opstår deadlocks eller timeouts i de applikationer, der benytter DB2. Jeg vil i dette tip komme med et lille bidrag til nedkæmpelsen af timeouts i forbindelse med INSERT's på tabeller med unique indexes.
Tippet giver kun mening, hvis to programmer samtidig prøver på at indsætte en række med samme unikke nøgle på den samme tabel. Det begrænser selvfølgelig udvalget af situationer, hvor tippet er relevant væsentligt. Jeg har benyttet det til at fjerne en dødirriterende timeout i en parallel afvikling af det samme program, hvor det viste sig, at to af de parallelt eksekverende jobs hele tiden ville indsætte den samme række på den samme tabel. Det ene job fik lov til at vente, mens det andet job fortsatte så længe uden at commit'te, at det ventende job til sidst fik en timeout. Normal løsning på den slags problemer er selvfølgelig at sætte commit-hyppigheden ned, men en skæv datafordeling og kravene til hastigheden gjorde, at det ikke var nogen god løsning.
Jeg fandt derfor på følgende udvej:
Jeg lavede simpelthen en SELECT før INSERT'en, der ved hjælp af en "dirty read" finder ud af, om rækken med den pågældende unikke værdi er til stede i tabellen. Fidusen er, at WITH UR gør det muligt for DB2 at se endnu ikke commit'tede ændringer. Derfor kan programmet nu selv kontrollere om det vil havne i en timeout-situation eller ej. Det gode ved denne løsning er, at programmet slet ikke kommer til at vente overhovedet, mens det dårlige er, at der skal bruges ekstra DB2-ressourcer på det ekstra og i princippet overflødige select-kald. Der er stadig en minimal risiko for at havne i en timeout, hvis det parallelt eksekverende program får kontrollen og laver sin insert, imens ovenstående programkode udfører IF'en.
Man kan også komme i den situation, at den programeksekvering, der først laver insert'en ender med at lave rollback. Så er det selvfølgelig ikke så godt, at vi lader som om, at rækken rent faktisk findes. Derfor skal man nøje overveje brugen af dette tip.
I min situation gjalt det om at opsamle nøgle-værdien til et efterfølgende job, som også var afhængig af, at de parallelt eksekverende jobs også blev afviklet OK. Hvis den anden programeksekvering lavede rollback, blev den restartet og ville derfor ved en efterfølgende succesfuld afslutning have opsamlet den manglede nøgle-værdi.