programmera.net -> oracle -> normal     för utskrift      info@programmera.net

Pessimistisk låsning i Oracle

1. Vad är pessimistisk låsning?
2. Steg1: Användare A söker fram Ford
3. Steg2: Användare B misslyckas med att söka fram Ford
4. Steg3: Användare A uppdaterar lönen för Ford

1. Vad är pessimistisk låsning?

Pessimistisk låsninging innebär att man låser raden i tabellen i samband med framsökningen av data. Under tiden från att raden är låst fram till och med att UPDATE utförs kan ingen annan uppdatera den aktuella raden. Denna metod är mycket bra men har följande nackdel:

  • Bra för client/server applikationer: En förutsättning för att pessimistisk låsning ska fungera är att det är samma databasuppkoppling som används för att låsa raden och för att sedan utföra uppdateringen. Client/server-applikationer består av en tung klient som jobbar direkt mot databasen. Varje klient har en egen koppling mot databasen och denna uppkoppling hålls vid liv ända tills klienten stängs ner. Därför är pessimistisk låsning idealisk för client/server.
På 90-talet då det var vanligt med client/server-applikationer fungerade pessimistisk låsning bra. Idag då tunna klienter är vanliga behåller en användare i princip aldrig samma databasuppkoppling mellan olika anrop mot servern. Därför är pessimistisk låsning en något utdaterad lösning för problemet med förlorad uppdatering. Hur som helst, bilden nedan visar ett exempel på hur pessimistisk låsning fungerar:



Stegen beskrivs översiktligt nedan:
  1. (tid 13:22:52) Användare A söker fram Ford (genom att göra en SELECT .. FOR UPDATE NOWAIT).
  2. (tid 13:25:16) Användare B misslyckas med att söka fram Ford (genom att göra en SELECT .. FOR UPDATE NOWAIT).
  3. (tid 13:26:31) Användare A uppdaterar lönen för Ford (genom att göra UPDATE och sedan COMMIT).
Nedan beskrivs stegen i detalj:

2. Steg1: Användare A söker fram Ford

Klockan 13:22:52 loggar användare A in på applikationen för att uppdatera data för en anställd vid namn "Ford" (som lagras i tabellen EMP). A söker fram "Ford" genom att använda siffran 7902 som är Fords anställningsnummer. Anta att den webbsida som visas efter sökningen ser ut såhär:



Vi simulerar själva sökningen i SQL*Plus genom att köra följande SELECT-sats:
SQL>  SELECT * FROM emp WHERE empno=7902 FOR UPDATE NOWAIT;

     EMPNO ENAME      JOB              MGR HIREDATE          SAL       COMM     DEPTNO
---------- ---------- --------- ---------- ---------- ---------- ---------- ----------
      7902 FORD       ANALYST         7566 1981-12-03       3000                    20

3. Steg2: Användare B misslyckas med att söka fram Ford

Klockan 13:25:16 vill användare B, som använder samma applikation, också uppdatera data för "Ford". B söker fram "Ford" på samma sätt som A men kommer att mötas av ett felmeddelande.



Vi simulerar denna sökning genom att öppna ett nytt terminalföster (eller MSDOS-fönster) och loggar in i SQL*Plus och kör samma SELECT-sats:
SQL>  SELECT * FROM emp WHERE empno=7902 FOR UPDATE NOWAIT;
SELECT * FROM emp WHERE empno=7902 FOR UPDATE NOWAIT
*
ERROR at line 1:
ORA-00054: resource busy and acquire with NOWAIT specified

Vi ser att vi möts av ett "ORA-00054" som indikerar att raden är låst.

4. Steg3: Användare A uppdaterar lönen för Ford

Klockan 13:26:31 bestämmer sig användare A (efter att ha stirrat på data för Ford i c.a. 4 minuter) för att uppdatera Fords lön från 3000 till 3200, se bild:



När A ny trycker på SUBMIT kommer samtliga data i formuläret skickas till databasen. Vi utgår från att applikationen alltid uppdaterar samtliga kolumner då man utför en UPDATE. Alltså ENAME sätts till "Ford" trots att det redan var "Ford" tidigare osv. För att simulera detta ska du utföra SQL-satsen nedan i den första SQL*Plus-terminalen:
SQL>  UPDATE emp SET ename='FORD', job='ANALYST', mgr=7566, sal=3200 WHERE empno=7902;

1 row updated.

SQL>  COMMIT;

Commit complete.

Nu ska det funka.