sql >> Database >  >> RDS >> Oracle

Optimistische vergrendeling implementeren in Oracle

Er zijn twee algemene benaderingen voor vergrendeling.

Ten eerste heb je pessimistische vergrendeling. In deze benadering vergrendelt u de rij (SELECT ... FOR UPDATE ) die voorkomt dat iemand anders de rij verandert. Dan doe je de UPDATE . Wanneer u uw wijziging vastlegt, wordt de vergrendeling vrijgegeven. Het is in dit geval niet nodig om een ​​versienummer/tijdstempelkolom te hebben (tenminste om vergrendeling niet te ondersteunen) en de code is relatief eenvoudig.

Het nadeel van pessimistische vergrendeling is dat u de vergrendeling moet vasthouden zolang een gebruiker op een pagina zit die mogelijk gegevens bewerkt. Dit is technisch heel moeilijk als je een webgebaseerde applicatie bouwt, aangezien HTTP een staatloos protocol is. Het verzoek dat de pagina in eerste instantie weergeeft, zou normaal gesproken een verbinding krijgen van de verbindingspool, doe de SELECT en breng de verbinding vervolgens terug naar de pool zodra de pagina klaar is. Het daaropvolgende verzoek om de gegevens bij te werken, gebeurt over het algemeen op een andere verbinding met een andere databasesessie, dus u kunt de rij in de eerste sessie niet vergrendelen en bijwerken in de tweede. Als je de rij pessimistisch wilde vergrendelen, zou je veel werk aan de back-end moeten doen om ervoor te zorgen dat de ene databaseverbinding was gekoppeld aan een bepaalde middelste laag-sessie totdat de gebruiker klaar was met het bewerken van de gegevens. Dit heeft over het algemeen zeer negatieve gevolgen voor de schaalbaarheid en introduceert allerlei problemen met sessiebeheer - hoe weet u bijvoorbeeld of ik een pagina heb opgevraagd, een rij heb vergrendeld en vervolgens mijn browser heb gesloten zonder ooit uit te loggen of een wijziging aan te brengen? Hoe lang laat je het record opgesloten in de database? Wat gebeurt er als een andere sessie de rij probeert te vergrendelen? Hoe lang laat je dat sessieblok wachten op een slot als de eerste persoon ging lunchen? Over het algemeen implementeren mensen geen pessimistische vergrendeling in webgebaseerde apps omdat het beheren van sessies en sessiestatus gewoon te onpraktisch is.

De tweede optie is optimistische vergrendeling. Bij deze benadering voegt u een versienummer/tijdstempel toe aan de rij. U selecteert dit versienummer/tijdstempel wanneer u de gegevens opvraagt. Dan gebruik je dit in je WHERE clausule wanneer u later de update uitvoert en controleert hoeveel rijen daadwerkelijk zijn gewijzigd. Als u precies één rij wijzigt, weet u dat de rij niet is gewijzigd sinds u deze leest. Als u 0 rijen wijzigt, weet u dat de rij is gewijzigd en kunt u de fout afhandelen.

U selecteert bijvoorbeeld de gegevens samen met het versienummer

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

Toen je klaar was om de update uit te voeren, zou je zoiets als dit doen waarbij je de version . gebruikt in uw UPDATE en een foutmelding geven als de rij is gewijzigd

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;

Uw toepassing zou dan iets nuttigs doen met de fout. Normaal gesproken zou dat betekenen dat je de gegevens opnieuw opvraagt, de wijzigingen aan de gebruiker presenteert en hen vraagt ​​​​of ze hun wijzigingen nog steeds willen toepassen. Als ik bijvoorbeeld een adres lees en het begin te bewerken, ga lunchen, mijn collega logt in, leest hetzelfde adres, wijzig het en sla het op, dan kom ik terug en probeer mijn wijzigingen op te slaan, dan is dat over het algemeen logisch om me iets te laten zien dat me vertelt dat mijn collega het adres al heeft gewijzigd in iets nieuws -- wil ik doorgaan met het maken van bewerkingen of wil ik ze verlaten.




  1. Wat is in een Oracle-database het verschil tussen ROWNUM en ROW_NUMBER?

  2. Hoe de BETWEEN-operator in SQL Server te gebruiken?

  3. Gegevensbeheer met Python, SQLite en SQLAlchemy

  4. Opgeslagen procedure - retourneer identiteit als uitvoerparameter of scalair