프린트 하기

OS 환경 : Oracle Linux 8.4 (64bit)

 

DB 환경 : Oracle Database 23.5.0.24.07 ai for Oracle Cloud and Engineered Systems

 

방법 : 오라클 23ai 신기능 Lock Free Reservation

오라클 23ai 부터 Lock-Free Reservation 기능이 도입되었음
이 기능은 잠금 없이 데이터베이스 자원을 예약할 수 있도록 하는 기능임
데이터베이스 자원에 대한 동시 접근을 허용함으로써, 경합 상황에서도 잠금 대기 없이 작업을 빠르게 처리할 수 있음
이를 통해 트랜잭션 처리 속도를 높이고, 시스템의 병목 현상을 줄여줌
특히, 고가용성 환경에서 효율적인 자원 사용을 가능하게 하여 안정적인 성능을 보장함

 

 

제약사항
- pk 가 존재 해야함
- update 시 값과 더하기(+) 또는 빼기(-) 와 함께 사용해야함(값만 없데이트하거나, 값에 곱하기,나누기 등 사용불가)
- update 시 where 절에서는 pk 를 사용 해야함
- 저널테이블은 직접 수정불가함
- 예약 가능한 컬럼이 있는 경우 테이블을 삭제할 수 없음
(다른 블로그 글들은 삭제할수 없다고 설명하고 있지만 실제 테스트해본 결과 삭제가 됨(정식버전에서 확인이 필요할듯함))

 

 

테스트
1. Lock-free reservation 미사용시
2. Lock-free reservation 사용시

 

 

테스트
1. Lock-free reservation 미사용시
상품 테이블 생성

1
2
3
SQL> create table products (id number primary key, name varchar2(50), stock number);
 
Table created.

 

 

초기 데이터 삽입

1
2
3
4
SQL>
insert into products (id, name, stock) values (1, 'laptop', 100);
insert into products (id, name, stock) values (2, 'smartphone', 200);
commit;

 

 

재고 확인

1
2
3
4
5
6
7
8
SQL> 
col name for a15
select * from products;
 
        ID NAME                STOCK
-------------------------------
         1 Laptop                 100
         2 Smartphone             200

 

 

동시성 문제 시뮬레이션 (두 세션에서 동시에 실행한다고 가정)
세션1에서 update 수행

1
2
3
SQL> update products set stock = stock - 10 where id = 1;
 
1 row updated.

 

 

세션2에서 update 수행(세션 1이 커밋하기 전에 실행)

1
2
SQL> update products set stock = stock - 5 where id = 1;
(대기중)

이 업데이트는 세션 1이 커밋할 때까지 대기하게 됨

 

 

세션1에서 커밋

1
2
3
SQL> commit;
 
Commit complete.

 

 

세션 2의 업데이트가 이제 실행되고, 세션 2에서 커밋

1
2
3
SQL> commit;
 
Commit complete.

 

 

결과 확인

1
2
3
4
5
SQL> select * from products where id = 1;
 
        ID NAME                 STOCK
-------------------------------
         1 Laptop                  85

정상적으로 update 되었지만, 2개 세션이 동시에 update 되진 않음

 

 

2. Lock-free reservation 사용시
(위 테스트에서 그대로 진행)
stock 컬럼에 대해 Lock-free reservation 적용

1
2
3
SQL> alter table products modify (stock reservable);
 
Table altered.

 

 

유저의 테이블 조회

1
2
3
4
5
6
SQL> select table_name from user_tables;
 
TABLE_NAME
----------------------
PRODUCTS
SYS_RESERVJRNL_31482 <<<<

저널 테이블이 생성됨 31482는 PRODUCTS 테이블의 object_id 임

 

 

Lock-free reservation으로 동시성 문제 해결
세션1에서 update 수행

1
2
3
SQL> update products set stock = stock - 10 where id = 1;
 
1 row updated.

 

 

세션2에서 update 수행(세션 1이 커밋하기 전에 실행 가능)

1
2
3
SQL> update products set stock = stock - 5 where id = 1;
 
1 row updated.

이 업데이트는 즉시 실행되며 대기하지 않음

 

 

각 세션에서 products 테이블 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
#세션1
SQL> select * from products where id = 1;
 
        ID NAME                 STOCK
---------- --------------- ----------
         1 Laptop                  85
 
#세션2
SQL> select * from products where id = 1;
 
        ID NAME                 STOCK
---------- --------------- ----------
         1 Laptop                  85

값이 반영되어 있지 않음

 

 

각 세션에서 저널 테이블 확인

1
2
3
4
5
6
7
8
9
10
11
12
13
#세션1
SQL> select * from SYS_RESERVJRNL_31482;
 
ORA_SAGA_ID$                     ORA_TXN_ID$      ORA_STATUS$ ORA_ST         ID S STOCK_RESERVED
-------------------------------- ---------------- ----------- ------ ---------- - --------------
                                 09001300CA040000 ACTIVE      UPDATE          1 -             10
 
세션2
SQL> select * from SYS_RESERVJRNL_31482;
 
ORA_SAGA_ID$                     ORA_TXN_ID$      ORA_STATUS$ ORA_ST         ID S STOCK_RESERVED
-------------------------------- ---------------- ----------- ------ ---------- - --------------
                                 0C00030068000000 ACTIVE      UPDATE          1 -              5

저널테이블에 update 한 내용이 저장되어 있음
S컬럼(STOCK_OP)에 값을 더한건지 뺀건지 나와있고(-), STOCK_RESERVED 컬럼에 몇을 연산했는지 나와있음

 

 

각 세션에서 커밋

1
2
3
SQL> commit;
 
Commit complete.

 

 

최종 결과 확인

1
2
3
4
5
SQL> select * from products where id = 1;
 
        ID NAME                 STOCK
---------- --------------- ----------
         1 Laptop                  70

2개의 update 가 모두 반영됨

 

 

참고용
저널테이블 구조

1
2
3
4
5
6
7
8
9
10
SQL> desc SYS_RESERVJRNL_31482
 Name                Null?    Type
 ------------------- -------- -----------------
 ORA_SAGA_ID$                 RAW(16)
 ORA_TXN_ID$                  RAW(8)
 ORA_STATUS$                  VARCHAR2(11)
 ORA_STMT_TYPE$               VARCHAR2(6)
 ID                  NOT NULL NUMBER
 STOCK_OP                     VARCHAR2(1)
 STOCK_RESERVED               NUMBER

 

 

결론 :
오라클 23ai 부터 Lock-Free Reservation 기능이 추가되면서 경합 상황에서도 대기 없이 업데이트를 처리할 수 있게 됨
기존에는 동시에 두 세션이 같은 데이터를 수정하려고 하면 잠금 대기가 발생했지만, 이제는 저널 테이블을 통해 각 세션의 변경 내용을 기록해두고, 커밋 시 최종 결과를 반영하는 방식으로 동작함
예를 들어, 두 세션이 같은 재고 컬럼을 수정하는 경우에도 각 세션은 독립적으로 업데이트를 진행하고, 결과적으로 두 연산이 모두 반영됨. 이로 인해 병목 현상 없이 빠르게 트랜잭션을 처리할 수 있게 되었음
또한 PK가 존재하고, 더하기(+) 또는 빼기(-) 연산을 사용하는 조건만 지키면, 시스템이 알아서 경합 상황을 처리해주기 때문에 트랜잭션 처리의 유연성이 크게 향상됨
이 기능 덕분에 실시간으로 여러 업데이트가 발생하는 재고 관리 시스템이나 고성능 트랜잭션 환경에서 성능이 한층 더 좋아질 것으로 보임
그리고 본문에서는 적은 데이터로 테스트했지만 plsql 등 프로그램을 이용해서 수백, 수천건을 동시에 처리해보면 이 기능의 장점을 확실히 확인할 수 있을듯함

 

 

참조 : 

https://positivemh.tistory.com/1103

https://positivemh.tistory.com/1163

https://apex.oracle.com/pls/apex/features/r/dbfeatures/features?feature_id=1805
https://docs.oracle.com/en/database/oracle/oracle-database/23/adfns/using-lock-free-reservation.html
https://docs.oracle.com/en/database/oracle/oracle-database/23/cncpt/tables-and-table-clusters.html#GUID-7C6A8E8A-F634-4D0D-877A-F948D6101066
https://www.youtube.com/watch?v=h6YvDoBfeyg
https://blogs.oracle.com/coretec/post/lock-free-reservation-in-23c
https://blogs.oracle.com/coretec/post/lockfree-reservation-in-23c-scale-your-apps
https://github.com/oracle-devrel/technology-engineering/tree/main/data-platform/core-converged-db/database-23ai/lock-free_reservation
https://oradbdev.mathiasmagnusson.com/2024/06/27/23ai-lock-free-reservations/
https://oracle-base.com/articles/23/lock-free-reservations-23
https://tuna.tistory.com/103
https://tuna.tistory.com/104