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

Hvordan kan jeg automatisk låse borde op i Oracle efter en given tid?

For det første vil låsning af et bord ikke forhindre en anden session i at udstede SELECT udsagn mod dataene.

I session 1, hvis jeg låser bordet

SQL> lock table foo in exclusive mode;

Table(s) Locked.

Jeg kan derefter starte session 2 og forespørge dataene alt, hvad jeg vil have

SQL> select * from foo;

      COL1
----------
         1
         1

I Oracle blokerer forfattere ikke læsere, så du kan aldrig forhindre en anden session i at forespørge dataene i en tabel.

Det lyder som om det du forsøger at implementere er pessimistisk låsning. I det tilfælde, i stedet for at låse tabellen, laver du en SELECT FOR UPDATE der låser den særlige post, du har til hensigt at behandle. Så længe alle de andre sessioner også forsøger at lave en SELECT FOR UPDATE (afhængigt af Oracle-versionen, potentielt tilføjelse af SKIP LOCKED qualifier og/eller WAIT kvalifikation). Det låser den specifikke række, du behandler, og lader den anden session enten vælge en anden række eller time-out eller finde ud af, at der ikke er nogen rækker at behandle, afhængigt af detaljerne i implementeringen. Det involverer ikke at låse bordet.

Den eneste måde, hvorpå en lås kan frigives, er, at den session, der erhvervede den, frigiver den (generelt ved at afslutte transaktionen), eller at den session, der erhvervede den, afsluttes. Hvis klientapplikationen stadig kører, men ikke gør noget for at frigøre låsen eller afslutte sessionen, vil låsen blive tilbageholdt på ubestemt tid. En DBA ville være nødt til eksplicit at dræbe sessionen, lade transaktionen rulle tilbage og frigive låsen for at få systemet i gang igen. Hvis klientapplikationen holder op med at køre eller i det mindste holder op med at reagere (jeg er stadig ikke klar over, præcist hvilket fejlscenarie du diskuterer), er det muligt at aktivere dead-connection detection (DCD) via 'SQLNET.EXPIRE_TIME'-parameter på databaseniveau ville få databasen til at bestemme, at klienten ikke reagerer og automatisk dræbe sessionen, rulle transaktionen tilbage og frigive låsen.

Hvis der er flere sessioner, der behandler data, er det dog generelt meget at foretrække at bruge en form for optimistisk låsning. Ellers designer du et system, der uundgåeligt vil have brug for, at DBA hurtigt finder og dræber sessioner for at få forretningsbrugerne til at arbejde igen, og som vil kræve mere og mere indgriben, jo travlere det bliver. Det er ikke noget, DBA'er kan lide at gøre, og ikke noget forretningsbrugere nyder at klage over. En simpel optimistisk låseordning ville så noget lignende

  • Vælg en nøgle, der skal behandles, og en slags dato, der angiver sidste gang, rækken blev opdateret.
  • Opdater en statuskolonne til "behandler", så andre sessioner ikke forsøger at behandle den samme række.
  • Behandle indtastningen i din ansøgning
  • Når du er færdig med at behandle, skal du opdatere dataene ved hjælp af nøglen og det tidspunkt, du valgte i det første trin. Hvis du opdaterer 1 række, ved du, at ingen anden session har ændret de pågældende data, siden du valgte dem. Hvis du opdaterer 0 rækker, ved du, at en anden session har ændret dataene, siden du valgte dem.

Med denne form for arkitektur er det relativt nemt at forespørge databasen for at se, hvilke rækker der behandles og for eksempel have et job, der sætter statuskolonnen tilbage til "ubehandlet" efter et stykke tid, hvis klienten ikke har færdig. Det er virkelig nemt for andre sessioner at vælge en anden række at behandle. Og det er relativt sikkert, hvis applikationen f.eks. fryser i et par timer og derefter genopretter sig, da den bare opdager, når den er færdig med at behandle, at en anden session allerede har genbehandlet rækken.




  1. Problemer med at binde et imploderet array til en mysql-forberedt erklæring

  2. Skal jeg åbne flere databaseforbindelser eller dele 1 i PHP/MySQL?

  3. ER_ACCESS_DENIED_ERROR:Når jeg forsøger at oprette forbindelse til databasen på fjernserveren - Node.js

  4. Drop Time i DateTime