Ten eerste zal het vergrendelen van een tafel niet voorkomen dat een andere sessie SELECT
. uitgeeft verklaringen tegen de gegevens.
Als ik in sessie 1 de tafel vergrendel
SQL> lock table foo in exclusive mode;
Table(s) Locked.
Ik kan dan Sessie 2 starten en alle gegevens opvragen die ik maar wil
SQL> select * from foo;
COL1
----------
1
1
In Oracle blokkeren schrijvers geen lezers, dus u kunt nooit voorkomen dat een andere sessie de gegevens in een tabel opvraagt.
Het klinkt alsof wat u probeert te implementeren pessimistische vergrendeling is. In dat geval doet u, in plaats van de tabel te vergrendelen, een SELECT FOR UPDATE
die de specifieke invoer vergrendelt die u wilt verwerken. Zolang alle andere sessies ook proberen een SELECT FOR UPDATE
(afhankelijk van de Oracle-versie, mogelijk het toevoegen van de SKIP LOCKED
kwalificatie en/of de WAIT
kwalificatie). Dat vergrendelt de specifieke rij die u aan het verwerken bent en laat de tweede sessie ofwel een andere rij selecteren of een time-out geven of ontdekken dat er geen rijen zijn om te verwerken, afhankelijk van de specifieke kenmerken van de implementatie. Dat houdt niet in dat de tafel wordt vergrendeld.
De enige manier om een blokkering op te heffen, is dat de sessie die het heeft verkregen, het vrijgeeft (meestal door de transactie te beëindigen) of dat de sessie die het heeft verkregen, wordt beëindigd. Als de clienttoepassing nog steeds actief is maar niets doet om de vergrendeling op te heffen of de sessie te beëindigen, wordt de vergrendeling voor onbepaalde tijd vastgehouden. Een DBA zou de sessie expliciet moeten beëindigen, de transactie laten terugdraaien en de vergrendeling vrijgeven om het systeem weer in beweging te krijgen. Als de clienttoepassing niet meer wordt uitgevoerd of in ieder geval niet meer reageert (het is mij nog steeds niet precies duidelijk welk storingsscenario u aan het bespreken bent), is het mogelijk dat het inschakelen van detectie van dode verbindingen (DCD) via de 'SQLNET.EXPIRE_TIME'-parameter op databaseniveau zou ervoor zorgen dat de database bepaalt dat de client niet reageert en de sessie automatisch afbreekt, de transactie terugdraait en de vergrendeling opheft.
Als er echter meerdere sessies gegevens verwerken, verdient het over het algemeen de voorkeur om een of andere vorm van optimistische vergrendeling te gebruiken. Anders ontwerp je een systeem dat onvermijdelijk de DBA nodig heeft om sessies dringend te vinden en te beëindigen om de zakelijke gebruikers weer aan het werk te krijgen en dat meer en meer interventie vereist naarmate het drukker wordt. Dat is niet iets dat DBA's graag doen en niet iets waar zakelijke gebruikers graag over klagen. Een eenvoudig optimistisch vergrendelingsschema zou zoiets als
- Selecteer een sleutel om te verwerken en een soort datum die aangeeft wanneer de rij voor het laatst is bijgewerkt.
- Update een statuskolom naar 'verwerken' zodat andere sessies niet proberen diezelfde rij te verwerken.
- Verwerk de invoer in uw aanvraag
- Als je klaar bent met verwerken, werk je de gegevens bij met de toets en de tijd die je in de eerste stap hebt geselecteerd. Als u 1 rij bijwerkt, weet u dat geen enkele andere sessie de betreffende gegevens heeft gewijzigd sinds u deze hebt geselecteerd. Als u 0 rijen bijwerkt, weet u dat een andere sessie de gegevens heeft gewijzigd sinds u deze heeft geselecteerd.
Met dit soort architectuur is het relatief eenvoudig om de database te doorzoeken om te zien welke rijen worden verwerkt en om bijvoorbeeld een taak te hebben die de statuskolom na een bepaalde periode terugzet op "onverwerkt" als de client dat niet heeft gedaan. afgerond. Het is heel eenvoudig voor andere sessies om een andere rij te kiezen om te verwerken. En het is relatief veilig als de toepassing bijvoorbeeld een paar uur vastloopt en daarna herstelt, omdat het pas ontdekt dat een andere sessie de rij al opnieuw heeft verwerkt zodra het klaar is met verwerken.