Oracle 21C区块链表

何为区块链表

Blockchain Tables

https://blogs.oracle.com/database/post/introducing-oracle-database-21c

区块链作为一种技术,在解决与交易验证相关的许多问题方面已经做出了很大的承诺。
虽然在将这项技术引入企业方面取得了相当大的进展,但仍存在一些问题。
可以说,最大的问题是构建支持分布式账本的应用程序的复杂性。
Oracle Database 21c通过引入区块链表解决了这个问题。
这些表的操作与任何普通堆表一样,但有许多重要的区别。
其中最值得注意的是,行在插入到表中时会进行加密散列,以确保以后不再更改该行。

Blockchain as a technology has promised much in terms of solving many of the problems associated with the verification of transactions. While considerable progress has been made in bringing this technology to the enterprise, a number of problems exist. Arguably, the largest being the complex nature of building applications that can support a distributed ledger. Oracle Database 21c addresses this problem with the introduction of Blockchain Tables. 
These tables operate like any normal heap table, but with a number of important differences. The most notable of these being that rows are cryptographically hashed as they are inserted into the table, ensuring that the row can no longer be changed at a later date.


实验:

数据库版本: Oracle 21C

SQL> select banner from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 21c Enterprise Edition Release 21.0.0.0.0 - Production

PDB名称:CJCPDB1

SQL> show pdbs
    CON_ID CON_NAME  OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
 2 PDB$SEED  READ ONLY  NO
 3 CJCPDB1  MOUNTED

实例状态:

SQL> select con_id,dbid,name,open_mode from v$pdbs;
    CON_ID DBID NAME   OPEN_MODE
---------- ---------- -------------------- ----------
 2  643081980 PDB$SEED   READ ONLY
 3 1808035318 CJCPDB1   MOUNTED

启动PDB:

SQL> alter pluggable database CJCPDB1 open;
SQL> select con_id,dbid,name,open_mode from v$pdbs;

进入pdb数据库

SQL> alter session set container=CJCPDB1;
SQL> show pdbs
    CON_ID CON_NAME  OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
 3 CJCPDB1  READ WRITE NO

查看数据文件

SQL> select name from v$dbfile;
NAME
--------------------------------------------------------------------------------
/oracle/app/oracle/oradata/CJC/cjcpdb1/system01.dbf
/oracle/app/oracle/oradata/CJC/cjcpdb1/sysaux01.dbf
/oracle/app/oracle/oradata/CJC/cjcpdb1/undotbs01.dbf
/oracle/app/oracle/oradata/CJC/cjcpdb1/users01.dbfile

创建测试表空间cjc_tbs和测试用户cjc、chen。

SQL> create tablespace cjc_tbs datafile '/oracle/app/oracle/oradata/CJC/cjcpdb1/cjc_tbs01a.dbf' size 10M autoextend on;
SQL> create user cjc identified by a default tablespace cjc_tbs;
SQL> create user chen identified by a default tablespace cjc_tbs;
SQL> GRANT connect,resource,dba to cjc;
SQL> GRANT unlimited tablespace TO cjc;
SQL> GRANT execute ON sys.dbms_blockchain_table TO cjc;
SQL> GRANT connect,resource,dba to chen;
SQL> GRANT unlimited tablespace TO chen;
SQL> GRANT execute ON sys.dbms_blockchain_table TO chen;

连接cjc用户

SQL> conn cjc/a@192.168.31.100:1521/cjcpdb1
Connected.
SQL> show user
USER is "CJC"

创建区块链表ledger_emp。

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.

通过user_blockchain_tables查看区块链表的属性。

Verify the attributes set for the blockchain table in the appropriate data dictionary view.

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
------------- --- -------------------------- --------
       365000 YES  31 SHA2_512

查看表结构

Show the description of the table.

SQL> DESC ledger_emp
 Name   Null?    Type
 ----------------------------------------- -------- ----------------------------
 EMPLOYEE_ID    NUMBER
 SALARY     NUMBER

DESC仅显示可见列。

使用USER_TAB_COLS视图显示内部隐藏列名。

SET PAGESIZE 100
COL "Data Length" FORMAT 9999
COL "Column Name" FORMAT A24
COL "Data Type" FORMAT A28
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
        12 ORABCTAB_SPARE$          RAW                                 2000
12 rows selected.

步骤2:插入数据

Step 2 : Insert rows into the blockchain table

插入第一行数据。

Insert a first row into the blockchain table.

SQL> INSERT INTO ledger_emp VALUES (106,12000);
1 row created.
SQL> COMMIT;
Commit complete.

显示第一行的内部值。

Display the internal values of the first row of the chain.

SQL>
SET LINE 300
COL "Chain HASH" FOR A30
COL "Chain date" FORMAT A17
COL "Chain ID" FORMAT 99999999
COL "Seq Num" FORMAT 99999999
COL "User Num" FORMAT 9999999
COL "Chain HASH" FORMAT 99999999999999
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
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
       24  1 14-Nov-2021 10-11   110
C66C6E3C124BA8B517827F357A86C7941419B0D22B502583BE118AF3D3DBD45EF15B20F446DD76F190691471B37A830CEF2E99D5885B9DEF678E7538C76A918D

以cjc身份连接并在区块链表中插入一行数据。

SQL> conn cjc/a@192.168.31.100:1521/cjcpdb1
SQL> GRANT insert ON ledger_emp TO chen;

插入数据

SQL> conn chen/a@192.168.31.100:1521/cjcpdb1
SQL> INSERT INTO  cjc.ledger_emp VALUES (106,24000);
1 row created.
SQL> COMMIT;
Commit complete.

查看数据

SQL> conn cjc/a@192.168.31.100:1521/cjcpdb1
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_IDSALARY
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ----------- ----------
       24  1 14-Nov-2021 10-11   110
C66C6E3C124BA8B517827F357A86C7941419B0D22B502583BE118AF3D3DBD45EF15B20F446DD76F190691471B37A830CEF2E99D5885B9DEF678E7538C76A918D      106 12000
       24  2 14-Nov-2021 10-20   111
C172CB59794C574E62B21AC82F054129D94AD45988C90D685EDBA58D293A89D635FB6475FB0E0F781F8A6F566E764315A8F5CA0225072D622E5AABCC258F7810      106 24000

步骤3:删除表数据

SQL> DELETE FROM ledger_emp WHERE ORABCTAB_USER_NUMBER$ = 119;
DELETE FROM ledger_emp WHERE ORABCTAB_USER_NUMBER$ = 119
          *
ERROR at line 1:
ORA-05715: operation not allowed on the blockchain table

不能使用delete命令删除区块链表中的行。

可以使用DBMS_BLOCKCHAIN_TABLE包删除区块链中的数据。

SQL>
SET SERVEROUTPUT ON
DECLARE
   NUMBER_ROWS NUMBER;
BEGIN
   DBMS_BLOCKCHAIN_TABLE.DELETE_EXPIRED_ROWS('CJC','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.

使用DBMS_BLOCKCHAIN_TABLE包删除区块链表中的行,只能删除保留期之外的行。

这就是为什么存储过程执行成功但是没有删除任何行的原因。

truncate表

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

指定在创建行15天后才能删除行。

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-05741: minimum retention time too low, should be at least 16 days

为什么不能更改此属性?您创建了具有“NO DELETE LOCKED”属性的表。

Why can't you change this attribute? You created the table with the  NO DELETE LOCKED attribute. 

LOCKED子句表示以后不能修改行保留。

The LOCKED clause indicates that you can never subsequently modify the row retention.

步骤4:drop表

Step 4 : Drop the blockchain table

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

区块链表的创建时限制了在31天内不能删除。

The blockchain table was created so that it cannot be dropped before 31 days of inactivity.

更改表的行为以允许较低的保留率。

Change the behavior of the table to allow a lower retention.

SQL> ALTER TABLE ledger_emp NO DROP UNTIL 1 DAYS IDLE;
ALTER TABLE auditor.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.

只能增加保留值。

这禁止删除出于安全目的需要保留的任何历史信息。

You can only increase the retention value. 

This prohibits dropping and removing any historical information that needs to be kept for security purposes.

#####chenjuchao 20220102 16:10#####

请使用浏览器的分享功能分享到微信等