Oracle 23c new features:  Lock-free reservation

Oracle 23c new features:  Lock-free reservation. Nu Oracle steeds meer informatie vrijgeeft over de nieuwe 23c release van de database, is het goed eens te kijken naar leuke en nuttige nieuwe features. Sommige van de wijzigingen zijn zo duidelijk nuttig toepasbaar dat je je afvraagt waarom bestaat dat niet al jaren. In dit artikel nemen we een van de meest spraakmakende nieuwe features onder de loep: Lock-free reservations.

Volgens de nieuw feature documentatie maakt lock-free reservation het mogelijk dat een applicatie een waarde in een kolom reserveert zonder de rij te locken; reserveer bijvoorbeeld een deel van een bankrekeningsaldo of reserveer een item in inventaris zonder alle andere bewerkingen op de bankrekening of het item uit te sluiten.

Dit betekent in de praktijk dat tijdens het creëren van de table een kolom als als reservable gemarkeerd kan worden:

create table inventory 
     (id number primary key,
     descr varchar2(25),
     amnt    number reservable);

insert into inventory values 
       (1,'aap', 10)
     , (2,'noot', 20)
     , (3,'mies', 30)
     , (4,'teun', 40);

commit;

desc inventory
Name  Null?    Type         
----- -------- ------------ 
ID    NOT NULL NUMBER       
DESCR          VARCHAR2(25) 
AMNT  NOT NULL NUMBER  

Het idee van de lock-free reservations   je vanuit 2 sessies een update kan doen op de reservable kolom zonder dat een van beiden blokkeert:

Sessie 1Sessie 2
update inventory  set amnt=amnt+1  where id=1; 
 update inventory  set amnt=amnt+1  where id=1;

En dat is ook het geval. Opvallend is dat als je in een van beide sessies de table uitvraagt na de update:

select * from inventory where id=1;
1	aap	10

Dit is anders dan je zo verwachten omdat je zou verwachten dat je je eigen niet commited update wel zou zien. Het is daarmee tijd om te kijken naar de manier waarop Oracle deze functionaliteit implementeert:

select * from user_objects;
INVENTORY			85419	85419	TABLE
SYS_RESERVJRNL_85419	85420	85420	TABLE
SYS_C008302			85421	85421	INDEX

Dit toont een extra object: het reservation journal.  Als we nu echt even proberen te duiken in wat oracle doet, moeten we tracing in een sessie aanzetten:

BEGIN DBMS_SESSION.SET_SQL_TRACE(sql_trace => true); END;

update inventory  
set amnt=amnt+1  where id=1;

commit;

De trace file  die daarna gegenereerd word bevat een drietal interessante sql-commando’s:

1SELECT NVL(((select NVL(sum(AMNT_RESERVED), 0)from RES_USER.SYS_RESERVJRNL_85419 where ORA_STATUS$ = 'ACTIVE' and AMNT_OP = '+' and ID = :VAL1 ) - (selectNVL(sum(AMNT_RESERVED), 0) from RES_USER.SYS_RESERVJRNL_85419 where ORA_STATUS$ = 'ACTIVE' and AMNT_OP = '-' and  ORA_TXN_ID$ = :TXID and ID = :VAL1 )), 0) as curr_reserv from dual
2INSERT INTO "RES_USER"."SYS_RESERVJRNL_85419" (ORA_SAGA_ID$, ORA_TXN_ID$, ORA_STATUS$, ORA_STMT_TYPE$, "AMNT_OP", "AMNT_RESERVED", "ID")VALUES (:1, :2, :3, :4, :5, :6, :7)
3update (select B$.ID,B$.AMNT,ORA_ESCR_AGG$.AMNT_RESVAL from RES_USER.INVENTORY B$ inner join (select EJ$.ID,NVL(sum(case when AMNT_OP = '+' then AMNT_RESERVED when AMNT_OP = '-' then -1*AMNT_RESERVED else 0 end), 0) as AMNT_RESVAL  from RES_USER.SYS_RESERVJRNL_85419 EJ$ where ORA_TXN_ID$=:1 and ORA_STATUS$='ACTIVE' and ORA_SAGA_ID$ IS NULL group by  EJ$.ID order by EJ$.ID desc) ORA_ESCR_AGG$ on B$.ID=ORA_ESCR_AGG$.ID) ORA_ESCR_JOIN$ set ORA_ESCR_JOIN$.AMNT = ORA_ESCR_JOIN$.AMNT +ORA_ESCR_JOIN$.AMNT_RESVAL

Als we deze commando’s bekijken zien we dat eerst gekeken wordt of deze transactie al een reservering heeft  (1) en zo niet (ons geval) er een insert in de reservation tabel wordt gedaan (2) en bij de commit wordt de daadwerkelijke update op de base tabel uitgevoerd(3).

Dit heeft als gevolg dat  een eventuele hang op een row lock  pas tijdens commit optreedt.

update inventory  set amnt=amnt+1  where id=1; 
 update inventory set descr='schapen'  where id=1;
commit;

HANG
 

De lock-free reservation is gemaakt voor die transactieverwerkende systemen waarbij een enkele nummer-veld intensief geüpdatet wordt. En zo is het mogelijk lock contentie hier te voorkomen.  Dit werkt alleen als de andere kolommen relatief statisch zijn. Naast deze logische beperking stelt Oracle ook een aantal beperkingen aan de reservable kolom.  Zo moet er een primary key zijn, is de reservable kolom van een nummer type  en kunnen er allen + en – operaties uitgevoerd worden.

Al met al is de lock free reservation een heel bruikbaar concept in applicatie ontwikkeling. Voor de DBA is het belangrijk het concept te kennen zodat bij lock contentie deze situatie correct geïnterpreteerd kan worden.

We hopen dat we je met dit artikel ‘Oracle 23c new features:  Lock-free reservation‘ op weg hebben geholpen. Mocht je hulp nodig hebben of je hebt vragen n.a.v. dit artikel, laat het ons dan weten.

Oracle Security en patching

Scroll to Top