sql >> Databáze >  >> RDS >> Oracle

Implementace Optimistic Locking v Oracle

Existují dva obecné přístupy k zamykání.

Za prvé, máte pesimistické zamykání. V tomto přístupu uzamknete řádek (SELECT ... FOR UPDATE ), což brání komukoli jinému změnit řádek. Poté provedete UPDATE . Když provedete změnu, zámek se uvolní. V tomto případě není potřeba mít sloupec číslo verze/časové razítko (alespoň ne pro podporu zamykání) a kód je relativně snadný.

Nevýhodou pesimistického zamykání je, že musíte zámek držet po celou dobu, kdy uživatel sedí na stránce, kde může potenciálně upravovat data. To je technicky opravdu těžké, pokud vytváříte webovou aplikaci, protože HTTP je bezstavový protokol. Požadavek, který zpočátku vykresluje stránku, by normálně získal připojení z fondu připojení, proveďte SELECT a po dokončení stránky vraťte připojení k fondu. Následný požadavek na aktualizaci dat by se obecně uskutečnil na jiném připojení s jinou databázovou relací, takže nemůžete zamknout řádek v první relaci a aktualizovat jej ve druhé. Pokud byste chtěli pesimisticky zamknout řádek, museli byste udělat hodně práce na back-endu, abyste zajistili, že jedno připojení k databázi bude svázáno s konkrétní relací střední vrstvy, dokud uživatel neukončí úpravy dat. To má obecně velmi negativní dopad na škálovatelnost a přináší nejrůznější problémy se správou relací – jak například víte, zda jsem požádal o stránku, zamkl řádek a poté zavřel prohlížeč, aniž bych se kdy odhlásil nebo provedl změnu? Jak dlouho necháte záznam uzamčený v databázi? Co se stane, když se nějaká jiná relace pokusí zamknout řádek? Jak dlouho necháte tuto relaci zablokovat čekání na zámek, pokud první osoba šla na oběd? Lidé obecně neimplementují pesimistické zamykání ve webových aplikacích, protože správa relací a stavu relace je příliš nepraktická.

Druhou možností je optimistické zamykání. V tomto přístupu přidáte do řádku číslo verze/časové razítko. Toto číslo verze/časové razítko vyberete při dotazu na data. Pak to použijete ve svém WHERE klauzuli, když později provedete aktualizaci a zkontrolujete, kolik řádků bylo skutečně změněno. Pokud upravíte přesně jeden řádek, víte, že se řádek nezměnil od doby, kdy jste jej přečetli. Pokud upravíte 0 řádků, víte, že se řádek změnil, a můžete chybu zvládnout.

Takže byste například vybrali data spolu s číslem verze

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

Když jste byli připraveni provést aktualizaci, udělali byste něco takového, kde byste použili version ve vašem UPDATE a vyvolá chybu, pokud se řádek změnil

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;

Vaše aplikace by pak s chybou udělala něco užitečného. Normálně by to znamenalo udělat něco jako znovu se dotazovat na data, prezentovat změny uživateli a zeptat se jich, zda stále chtějí své změny použít. Když si například přečtu adresu a začnu ji upravovat, jdu na oběd, kolega se přihlásí, přečte stejnou adresu, provede nějaké úpravy a uloží ji, tak se vrátím a zkusím uložit své změny, obecně by to dávalo smysl aby mi ukázal něco, co mi říká, že můj kolega již změnil adresu na něco nového – chci pokračovat v úpravách nebo je chci opustit.




  1. Metoda upgradu není volána v android sqlite

  2. Použití sekvence PostgreSQL v režimu spánku neovlivňuje tabulku sekvencí

  3. Jak funguje funkce REPLICATE() v SQL Server (T-SQL)

  4. Doporučené postupy protokolování auditu PostgreSQL