sql >> Database teknologi >  >> RDS >> Oracle

Implementering af Optimistic Locking i Oracle

Der er to generelle tilgange til låsning.

For det første har du pessimistisk låsning. I denne tilgang låser du rækken (SELECT ... FOR UPDATE ), som forhindrer andre i at ændre rækken. Så laver du UPDATE . Når du foretager din ændring, udløses låsen. Der er ikke behov for i dette tilfælde at have et versionsnummer/tidsstempelkolonne (i hvert fald ikke for at understøtte låsning), og koden er forholdsvis nem.

Ulempen ved pessimistisk låsning er, at du skal holde låsen, hele tiden en bruger sidder på en side, der potentielt redigerer data. Dette er teknisk rigtig svært, hvis du bygger en webbaseret applikation, da HTTP er en statsløs protokol. Forespørgslen, der oprindeligt gengiver siden, vil normalt få en forbindelse fra forbindelsespuljen. Udfør SELECT , og returner derefter forbindelsen til poolen, når siden er færdig. Den efterfølgende anmodning om at opdatere dataene ville generelt ske på en anden forbindelse med en anden databasesession, så du kan ikke låse rækken i den første session og opdatere den i den anden. Hvis du pessimistisk ville låse rækken, skulle du gøre en masse arbejde på bagenden for at sikre, at den ene databaseforbindelse var bundet til en bestemt mellemtrinssession, indtil brugeren var færdig med at redigere dataene. Dette har generelt en meget negativ indvirkning på skalerbarheden og introducerer alle mulige sessionsstyringsproblemer - hvordan ved du for eksempel, om jeg har anmodet om en side, låst en række og derefter lukket min browser uden nogensinde at logge ud eller foretage en ændring? Hvor længe vil du lade posten være låst i databasen? Hvad sker der, hvis en anden session forsøger at låse rækken? Hvor længe vil du lade den session blokere og vente på en låsning, hvis den første person gik ud til frokost? Generelt implementerer folk ikke pessimistisk låsning i webbaserede apps, fordi administration af sessioner og sessionstilstand bare er for upraktisk.

Den anden mulighed er optimistisk låsning. I denne tilgang tilføjer du et versionsnummer/tidsstempel til rækken. Du vælger dette versionsnummer/tidsstempel, når du forespørger dataene. Så bruger du dette i din WHERE klausul, når du senere laver opdateringen og kontrollerer, hvor mange rækker der rent faktisk blev ændret. Hvis du ændrer præcis én række, ved du, at rækken ikke har ændret sig, siden du læste den. Hvis du ændrer 0 rækker, ved du, at rækken ændrede sig, og du kan håndtere fejlen.

Så for eksempel skal du vælge dataene sammen med versionsnummeret

SELECT address_line1, city, state, zip, version
  FROM addressTable
 WHERE address_id = `<<some key>>`

Når du var klar til at lave opdateringen, ville du gøre sådan noget, hvor du brugte version i din UPDATE og smid en fejl, hvis rækken ændrede sig

UPDATE addressTable
   SET address_line1 = `<<new address line 1>>`,
       city = `<<new city>>`,
       state = `<<new state>>`,
       zip = `<<new zip>>`,
       version = version + 1
 WHERE address_id = `<<some key>>`
   AND version = `<<version you read initially>>`

IF( SQL%ROWCOUNT = 0 )
THEN
  -- Darn.  The row must have changed since you read it.  Do something to
  -- alert the user.  Most likely, the application will need to re-query the
  -- data to see what the address has been changed to and then ask the user
  -- whether they want to re-apply the changes.
  RAISE_APPLICATION_ERROR( -20001, 'Oops, the row has changed since you read it.' );
END IF;

Din ansøgning ville så gøre noget nyttigt med fejlen. Normalt ville det betyde at gøre noget som at forespørge dataene igen, præsentere ændringerne for brugeren og spørge dem, om de stadig ønskede at anvende deres ændringer. Hvis jeg for eksempel læser en adresse og begynder at redigere den, går til frokost, min kollega logger ind, læser den samme adresse, laver nogle redigeringer og gemmer den, så vender jeg tilbage og prøver at gemme mine ændringer, det ville generelt give mening for at vise mig noget, der fortæller mig, at min kollega allerede har ændret adressen til noget nyt - vil jeg fortsætte med at redigere, eller vil jeg opgive dem.




  1. Returnerer et resultatsæt

  2. Forklar Planlæg Cost Pain Point

  3. Erklæring af tupelstrukturen af ​​en post i PL/pgSQL

  4. Brug MySQL relationsdatabaser på Fedora 14