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 1 | Sessie 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:
| 1 | SELECT 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 |
| 2 | INSERT 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) |
| 3 | update (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; |
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.

