본문 바로가기

Database/Oracle Database

21c 신기능 - 블록체인 테이블

아래 오라클 문서를 참조한 내용입니다.

Details: Oracle Blockchain Table
Practice: Managing Blockchain Tables and Rows

 

오라클 데이터베이스 21c 신기능 중 하나인 블록체인(Blockchain) 테이블에 대해서 살펴보겠습니다.

 

블록체인 테이블이란?

블록체인 테이블은 insert 작업만 허용되는 append 전용 테이블입니다. 로우(row)에 대한 삭제는 허용되지 않거나, 시간을 기준으로 제한이 됩니다. 블록체인 테이블의 로우는 내부 시퀀싱 및 체인 알고리즘에 의해 위변조가 방지되며, 사용자는 로우가 변조 여부를 확인할 수 있습니다. 로우의 메타데이터를 구성하는 해시 값은 로우를 연결하고 유효성을 검사하는 데 사용됩니다.

 

어디에 사용하나?

블록체인 테이블은 오라클 데이터베이스를 신뢰하면서, 동시에 데이터가 변조되지 않았는지 확인할 수단을 필요한 참여자가 블록체인 애플리케이션을 구현하는 데 사용할 수 있습니다. 여기서 참여자란 트랜잭션 블록체인을 사용하는 데이터베이스 유저들을 의미합니다. 블록체인 테이블은 오라클이 관리하는 몇 가지 추가 메타데이터와 함께 애플리케이션에 의해서 정의 및 관리됩니다. 이러한 오라클이 사용하는 이른바 중앙집중식 블록체인은 검증 가능한 암호화 보안 데이터 관리를 통해서 분산 합의 요건을 어느 정도 충족시킬 수 있습니다. 즉, 분산 P2P 블록체인의 보호 기능을 대부분 제공하지만 분산 합의를 사용하는 P2P 블록체인에 비해 높은 처리량과 짧은 트랜잭션 대기 시간을 제공합니다.

 

블록체인 테이블의 구조

블록체인 테이블은 로우를 여러 체인으로 구성하는 insert 전용 테이블로서, 블록체인 테이블 내 로우는 위변조를 할 수가 없습니다. 체인의 첫 번째 로우를 제외한 각 로우는 이전 로우에 연결되고, 각 로우에는 해당 로우의 데이터와 체인에 있는 이전 로우의 해시 값을 기반으로 하는 암호화 해시 값이 들어있습니다. 그래서 특정 로우가 변조되면 로우의 해시 값이 변경되고 이로 인해 체인에 있는 다음 로우의 해시 값이 변경됩니다. 추가적으로 보다 향상된 사기 탐지를 위해 사용자 서명을 로우에 추가할 수도 있습니다.

 

블록체인 테이블 사용 샘플

블록체인 테이블 소유 유저 "AUDITOR"를 만듭니다.

SQL> show user
USER is "SYS"

SQL> show con_name
CON_NAME
------------------------------
ORCL_PDB1

SQL> create tablespace ledgertbs datafile size 50m;
Tablespace created.

SQL> create user auditor identified by WElcome123## default tablespace ledgertbs;
User created.

SQL> grant create session, create table, unlimited tablespace to auditor;
Grant succeeded.

SQL> grant execute on sys.dbms_blockchain_table to auditor;
Grant succeeded.

SQL> grant select on hr.employees to auditor;
Grant succeeded.

 

AUDITOR.LEDGER_EMP 라는 이름으로 블록체인 테이블 생성합니다. 블록체인 테이블 "AUDITOR.LEDGER_EMP" 의 로우는 삭제될 수 없으며, 블록체인 테이블은 생성시 설정한 inactivity 일 수 이후에라야 drop될 수 있습니다.
블록체인 테이블 생성 시 NO DROP, NO DELETE, HASHING USING, VERSION 구문은 필수 사항입니다. 해당 옵션을 넣지 않을 경우, 블록 체인 테이블은 아래 예와 같이 생성되지 않습니다.

SQL> connect auditor/WElcome123##@orcl:1521/orcl_pdb1.snpublic.cluster1.oraclevcn.com
Connected.

SQL> create blockchain table ledger_emp (employee_id number, salary number);
create blockchain table ledger_emp (employee_id number, salary number)
                                                                     *
ERROR at line 1:
ORA-00905: missing keyword

SQL> create blockchain table ledger_emp (employee_id number, salary number)
          no drop until 31 days idle
          no delete locked
          hashing using "sha2_512" version "v1"; 

Table created.

SQL> select row_retention, row_retention_locked, table_inactivity_retention, hash_algorithm
from   user_blockchain_tables
where  table_name='LEDGER_EMP';

ROW_RETENTION ROW TABLE_INACTIVITY_RETENTION HASH_ALG
------------- --- -------------------------- --------
              YES                         31 SHA2_512

SQL> desc LEDGER_EMP
 Name                          Null?    Type
 ----------------------------- -------- --------------------
 EMPLOYEE_ID                            NUMBER
 SALARY                                 NUMBER

 

블록체인 테이블 생성 후에 user_tab_cols 뷰에서 user_number,  signature 등의 internal 정보를 저장하는 internal 칼럼명을 확인할 수 있습니다.

SQL> col "data length" format 9999
SQL> col "column name" format a24
SQL> col "data type" format a28
SQL> select internal_column_id "col id", substr(column_name,1,30) "column name", substr(data_type,1,30) "data type", data_length "data length"
from user_tab_cols
where table_name = 'LEDGER_EMP'
order by internal_column_id;

    col id column name              data type                    data length
---------- ------------------------ ---------------------------- -----------
         1 EMPLOYEE_ID              NUMBER                                22
         2 SALARY                   NUMBER                                22
         3 ORABCTAB_INST_ID$        NUMBER                                22
         4 ORABCTAB_CHAIN_ID$       NUMBER                                22
         5 ORABCTAB_SEQ_NUM$        NUMBER                                22
         6 ORABCTAB_CREATION_TIME$  TIMESTAMP(6) WITH TIME ZONE           13
         7 ORABCTAB_USER_NUMBER$    NUMBER                                22
         8 ORABCTAB_HASH$           RAW                                 2000
         9 ORABCTAB_SIGNATURE$      RAW                                 2000
        10 ORABCTAB_SIGNATURE_ALG$  NUMBER                                22
        11 ORABCTAB_SIGNATURE_CERT$ RAW                                   16

    col id column name              data type                    data length
---------- ------------------------ ---------------------------- -----------
        12 ORABCTAB_SPARE$          RAW                                 2000

12 rows selected.

 

블록체인 테이블에 첫번째 로우를 insert합니다. 체인의 첫번째 로우의 internal 값을 확인할 수 있습니다.

SQL> insert into ledger_emp values (106,12000);
1 row created.

SQL> commit;
Commit complete.

SQL> col "chain date" format a17
SQL> col "chain id" format 99999999
SQL> col "seq num" format 99999999
SQL> col "user num" format 9999999
SQL> col "chain hash" format 99999999999999
SQL> select orabctab_chain_id$ "chain id", orabctab_seq_num$ "seq num", to_char(orabctab_creation_time$,'dd-mon-yyyy hh-mi') "chain date", orabctab_user_number$ "user num", orabctab_hash$ "chain hash"
from   ledger_emp;

 chain id   seq num chain date        user num
--------- --------- ----------------- --------
chain hash
--------------------------------------------------------------------------------
       12         1 10-aug-2021 05-12      115
1122FEEF068FB883217041B4C5659B485EB7CB55B93DA5970FFC361C99E5CC84142F2B4C697322DC
A1925E8D35B115101C10C308BEE1C1BDF088E5EE1F773F34

 

어플리케이션에서 작동하는 방식으로 별도 HR 유저로 접속해서 블록체인 테이블에 데이터를 한건 입력합니다. 그 전에 우선 해당 테이블에 HR 유저에게 insert 권한을 부여했습니다.

SQL> grant insert on ledger_emp to hr;
Grant succeeded.

SQL> connect hr/We1c0me###DBA@orcl:1521/orcl_pdb1.snpublic.cluster1.oraclevcn.com
Connected.
SQL> show user
USER is "HR"

SQL> insert into  auditor.ledger_emp values (106,24000);
1 row created.

SQL> commit;
Commit complete.

 

AUDITOR 유저로 접속해서 블록체인 테이블의 internal 및 external 값을 조회해 봅니다.

SQL> connect auditor/WElcome123##@orcl:1521/orcl_pdb1.snpublic.cluster1.oraclevcn.com
Connected.
SQL> show user
USER is "AUDITOR"

SQL> select orabctab_chain_id$ "chain id", orabctab_seq_num$ "seq num", to_char(orabctab_creation_time$,'dd-mon-yyyy hh-mi') "chain date", orabctab_user_number$ "user num", orabctab_hash$ "chain hash", employee_id, salary
from   ledger_emp; 

 chain id   seq num chain date        user num
--------- --------- ----------------- --------
chain hash
--------------------------------------------------------------------------------
EMPLOYEE_ID     SALARY
----------- ----------
       12         1 10-aug-2021 05-12      115
1122FEEF068FB883217041B4C5659B485EB7CB55B93DA5970FFC361C99E5CC84142F2B4C697322DC
A1925E8D35B115101C10C308BEE1C1BDF088E5EE1F773F34
        106      12000

       12         2 10-aug-2021 06-49      109
CB24867F9F5782E937D9931424A076400DC252053F570B392E8865214CA4FE51FE5F4EBBD8DE8F29

 chain id   seq num chain date        user num
--------- --------- ----------------- --------
chain hash
--------------------------------------------------------------------------------
EMPLOYEE_ID     SALARY
----------- ----------
F463D74B1719B28CC0AFBBDD43CA28F461E2716AD71D625A
        106      24000

 

이번에는 앞서 HR 유저가 입력한 로우에 대한 삭제를 해 봅니다. 하지만 해당 오퍼레이션은 허용되지 않는다는 메세지를 받게 됩니다. 블록체인 테이블의 로우는 DELETE 명령으로 삭제할 수 없습니다. DBMS_BLOCKCHAIN_TABLE 패키지를 사용해야 합니다.

SQL> delete from ledger_emp where orabctab_user_number$ = 115;
delete from ledger_emp where orabctab_user_number$ = 115
            *
ERROR at line 1:
ORA-05715: operation not allowed on the blockchain table

 

앞서 블록체인 테이블의 로우는 DBMS_BLOCKCHAIN_TABLE 패키지를 이용해서만 삭제가 가능하다고 했지만, 하나 더 보존 기간이 지난 경우에만 삭제할 수 있습니다. 이때문에 아래 샘플처럼 프로시저는 실행되지만, 실제 로우는 삭제되지 않습니다.

SQL> set serveroutput on
SQL> declare
   number_rows number;
begin
   dbms_blockchain_table.delete_expired_rows('AUDITOR','LEDGER_EMP', null, number_rows);
   dbms_output.put_line('Number of rows deleted=' || number_rows);
end;
/
Number of rows deleted=0

PL/SQL procedure successfully completed.

 

TRUNCATE 명령 역시 블록체인 테이블에서는 허용되지 않습니다.

SQL> truncate table ledger_emp;
truncate table ledger_emp
               *
ERROR at line 1:
ORA-05715: operation not allowed on the blockchain table

 

DROP 테이블을 시도해 보겠습니다. 앞서 TRUNCATE 명령 때 발생했던 에러 메시지와 DROP TABLE 명령때의 에러 메세지가 다소 다릅니다. TRUNCATE TABLE 명령 시 에러 메세지는 해당 오퍼레이이션이 블록체인 테이블에서는 불가하다는 것이고, 이번 DROP TABLE 명령은 LEDGER_EMP 테이블에서 불가하다는 메시지입니다. 즉 DROP할 수는 있지만 31일 inactivity 전에는 DROP 할 수 없다는 의미입니다.

SQL> drop table ledger_emp;
drop table ledger_emp
           *
ERROR at line 1:
ORA-05723: drop blockchain table LEDGER_EMP not allowed

 

이번에는 블록체인 테이블 속성을 테이블 생성 후 15일까지는 데이터를 삭제를 할 수 없도록 지정해 보겠습니다. 이 경우 ORA-05731 에러와 함께 속성 변경을 할 수 없는데, 블록체인 테이블 생성 시점에 NO DELETE LOCKED 속성을 지정했기 때문입니다. LOCKED 구문은 로우의 보존기한을 수정할 수 없도록 하는 옵션입니다.

SQL> alter table ledger_emp no delete until 15 days after insert;
alter table ledger_emp no delete until 15 days after insert
*
ERROR at line 1:
ORA-05731: blockchain table LEDGER_EMP cannot be altered

 

테이블 로우 말고 DROP에 대한 속성 변경을 해 보겠습니다. 테이블 보존 주기에 대한 변경에서 그 기한을 늘리는 것은 가능하지만 줄이는 것은 불가합니다. 이는 보존이 필요한 이력 정보에 삭제하거나 DROP 하는 것을 방지하기 위함이다.

SQL> alter table ledger_emp no drop until 1 days idle;
alter table ledger_emp no drop until 1 days idle
*
ERROR at line 1:
ORA-05732: retention value cannot be lowered


SQL> alter table ledger_emp no drop until 40 days idle;

Table altered.

 

AUDITOR.LEDGER_TEST 라는 이름으로 블록체인 테이블을 하나 더 만들어 보겠습니다. 로우의 DELETE는 5일, 테이블 DROP은 1일 동안의 inactivity 이후에야 DELETE, DROP이 가능한 블록체인 테이블을 생성해 봅니다. 최소 보존 기한은 16일 이라는 메시지와 함께 실패합니다. 보존기한을 16일로 변경하면 생성이 됩니다.

SQL> create blockchain table auditor.ledger_test (id number, label varchar2(2))
       no drop until 1 days idle
       no delete until 5 days after insert
       hashing using "SHA2_512" version "v1"; 
create blockchain table auditor.ledger_test (id number, label varchar2(2))
*
ERROR at line 1:
ORA-05741: minimum retention time too low, should be at least 16 days

SQL> create blockchain table auditor.ledger_test (id number, label varchar2(2))
       no drop until 16 days idle
       no delete until 16 days after insert
       hashing using "SHA2_512" version "v1";

Table created.

 

HR 유저로 접속해서 블록체인 테이블에 로우 하나를 insert 합니다. 그 이전에 먼저 HR 유저에 앞서 생성한 테이블에 INSERT 권한 부여합니다.

SQL> grant insert on auditor.ledger_test to hr;
Grant succeeded.

SQL> connect hr/We1c0me###DBA@orcl:1521/orcl_pdb1.snpublic.cluster1.oraclevcn.com
Connected.
SQL> insert into auditor.ledger_test values (1,'A1');
1 row created.

SQL> commit;
Commit complete.

 

AUDITOR 유저로 접속해서 블록체인 테이블의 데이터 확인하고, DBMS_BLOCKCHAIN_TABLE.VERIFY_ROWS 패키지를 이용해서 로우의 내용이 유효한지 확인해 봅니다.

SQL> connect auditor/WElcome123##@orcl:1521/orcl_pdb1.snpublic.cluster1.oraclevcn.com
Connected.
SQL> select * from auditor.ledger_test;

        ID LA
---------- --
         1 A1

SQL> show user
USER is "AUDITOR"
SQL> set serveroutput on
SQL> declare
   row_count number;
   verify_rows number;
   instance_id number;
begin
  for instance_id in 1 .. 2 loop
    select count(*) into row_count from auditor.ledger_test where orabctab_inst_id$=instance_id;
    DBMS_BLOCKCHAIN_TABLE.VERIFY_ROWS('AUDITOR','LEDGER_TEST', null, null, instance_id, null, verify_rows);
    dbms_output.put_line('Number of rows verified in instance Id '|| instance_id || ' = '|| row_count);
  end loop;
end;
/
Number of rows verified in instance Id 1 = 1
Number of rows verified in instance Id 2 = 0

PL/SQL procedure successfully completed.