programmera.net -> oracle -> normal för utskrift | info@programmera.net |
Förlorad uppdatering
1. Förlorad uppdatering
På denna sida ska vi beskriva fenomenet med förlorad uppdatering (lost update). Förlorad uppdatering uppkommer oftast i applikationer men kan också inträffa för DBA-er som sitter och skriver SQL direkt i t.ex. SQL*Plus. Detta fenomen är ett mycket stort problem p.g.a:
Förlorad uppdatering beskrivs av bilden nedan:
Stegen beskrivs översiktligt nedan:
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;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- ---------- ---------- ---------- ----------
7902 FORD ANALYST 7566 1981-12-03 3000 20
3. Steg2: Användare B söker 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 och kommer att se samma data, se bilden:
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:
Anledningen till att vi öppnar ett nytt terminalfönster är att vi vill att användare B ska ha en egen anslutning till databasen.
[olle@dev1]$ sqlplus scott/tiger
SQL*Plus: Release 10.2.0.1.0 - Production on Sat Sep 2 09:44:36 2006
Copyright (c) 1982, 2005, Oracle. All rights reserved.
Connected to:
Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Production
With the Partitioning, OLAP and Data Mining options
SQL> SELECT * FROM emp WHERE empno=7902;
EMPNO ENAME JOB MGR HIREDATE SAL COMM DEPTNO
---------- ---------- --------- ---------- ---------- ---------- ---------- ----------
7902 FORD ANALYST 7566 1981-12-03 3000 20
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:
COMMIT utförs här direkt efter UPDATE eftersom användare A är klar med sin transaktion.OBS: Det kan tyckas dumt att applikationen uppdaterar samtliga kolumner vid varje update, men detta är faktiskt mycket vanligt. Orsaken till att man uppdaterar alla kolumner är:
SQL> UPDATE emp SET ename='FORD', job='ANALYST', mgr=7566, sal=3200 WHERE empno=7902;
1 row updated.
SQL> COMMIT;
Commit complete.
Alla applikationer jag har sett källkoden för uppdaterar samtliga kolumner, vare sig det behövs eller ej.
5. Steg4: Användare B ger Ford en ny chef
Klockan 13:29:20 byter Användare B chef för "Ford" så att MANAGER blir "King", se nedan:
Märk att användare Bs webbsida inte har uppdaterats med det nya värdet på lön, här står alltså det gamla värdet på lönen ("sal=3000") som var aktuellt när han sökte fram "Ford" klockan 13:25:16. Värdet 3000 skickas tillsammans med det nya värdet på MANAGER till servern och används i UPDATE-satsen (som uppdaterar samtliga fält, se ovan för diskussion om detta). För att simulera den UPDATE applikationen utför öppnar du den andra SQL*Plus-terminalen och skriver:
SQL> UPDATE emp SET ename='FORD', job='ANALYST', mgr=7839, sal=3000 WHERE empno=7902;
1 row updated.
SQL> COMMIT;
Commit complete.
6. Steg5: Användare A upptäcker att Fords lön inte har uppdaterats
När nu användare A klockan 14:11:10 loggar in på applikationen för att titta på data för Ford kommer han se att lönen har gått tillbaka till att bli 3000, men fältet MANAGER har uppdaterats till "King", se nedan:
För att själv kolla detta, kör följande SQL i någon av SQL*Plus-terminalerna:
SQL> SELECT sal FROM emp WHERE empno=7902;
SAL
----------
3000