在19c和21c中的区块链表

区块链表是一个仅插入的防篡改表,可以设置表级别或行级别的保留时间。行数据被组织到链中,每行数据包含一个hash算值,一个前一行数据的hash算值。

这个特性已经在19.10被后台引入,不过扔需要patch 32431413 ,并设定COMPATIBLE 参数到19.10.0或之后。从19.11开始,就不需要额外的补丁了。

在学习区块链表的时候,小心不要设置太长的保留时间,否则你会要等待很长的时间来删除测试表

  • 创建区块链表
  • 修改区块链表
  • 阻塞dml和ddl操作
  • DBMS_BLOCKCHAIN_TABLE包
  • 一些思考

创建区块链表

create table命令那里添加blockchain关键字,这里有3种区块链选项

no drop选项指定保护表不能被drop。如果表中没有数据,那仍然可以drop表,不像区块链表的初始版本(19.10和21.3),no drop选项同样防止了表被命令drop table ... cascade级联删除。

NO DROP [ UNTIL number DAYS IDLE ]
  • NO DROP : 这个表不能被drop,在测试时请小心
  • NO DROP UNTIL number DAYS IDLE : 这个表不能被drop,直到指定时间内没有新的数据行插入。你可能在测试时喜欢用0或者1天。

NO DELETE 选项指定保留的时间。每行数据会被保护多长时间不被删除。

NO DELETE { [ LOCKED ] | (UNTIL number DAYS AFTER INSERT [ LOCKED ]) }
  • NO DELETE :每行永久保留。没有LOCKED关键字的含有了这个表可以被alter table命令修改设置的意思。修改的保留时间只能更长。 
  • NO DELETE LOCKED : 与 NO DELETE相同。
  • NO DELETE UNTIL number DAYS AFTER INSERT : 每行保护指定的保留时间避免删除,不过这个设置可以被alter table命令增加。最小值为16天。
  • NO DELETE UNTIL number DAYS AFTER INSERT LOCKED : 每行保护指定的保留时间避免删除,而且这个设置不能被alter table命令修改。最小值为16天。

--碎碎念:这里可以看19c的sql language reference的create table子节的blockchain_row_retention_clause部分

快链 hash 和数据格式选项在当前版本中固定。它看起来会在将来的版本中允许修改hash算法。

HASHING USING sha2_512 VERSION v1

把所有选项放一起的语句像是下面:

--drop table bct_t1 purge;

create blockchain table bct_t1 (
  id            number,
  fruit         varchar2(20),
  quantity      number,
  created_date  date,
  constraint bct_t1_pk primary key (id)
)
no drop until 0 days idle
no delete until 16 days after insert
hashing using "SHA2_512" version "v1";

检查 USER_TAB_COLS 视图会显示若干不可见的列被加入到列表中。这些隐藏列描述如下。

set linesize 120 pagesize 50
column column_name format a30
column data_type format a27
column hidden_column format a13

select internal_column_id,
       column_name,
       data_type,
       data_length,
       hidden_column
FROM   user_tab_cols       
WHERE  table_name = 'BCT_T1'
ORDER BY internal_column_id;

INTERNAL_COLUMN_ID COLUMN_NAME                    DATA_TYPE                   DATA_LENGTH HIDDEN_COLUMN
------------------ ------------------------------ --------------------------- ----------- -------------
                 1 ID                             NUMBER                               22 NO
                 2 FRUIT                          VARCHAR2                             25 NO
                 3 QUANTITY                       NUMBER                               22 NO
                 4 CREATED_DATE                   DATE                                  7 NO
                 5 ORABCTAB_INST_ID$              NUMBER                               22 YES
                 6 ORABCTAB_CHAIN_ID$             NUMBER                               22 YES
                 7 ORABCTAB_SEQ_NUM$              NUMBER                               22 YES
                 8 ORABCTAB_CREATION_TIME$        TIMESTAMP(6) WITH TIME ZONE          13 YES
                 9 ORABCTAB_USER_NUMBER$          NUMBER                               22 YES
                10 ORABCTAB_HASH$                 RAW                                2000 YES
                11 ORABCTAB_SIGNATURE$            RAW                                2000 YES
                12 ORABCTAB_SIGNATURE_ALG$        NUMBER                               22 YES
                13 ORABCTAB_SIGNATURE_CERT$       RAW                                  16 YES
                14 ORABCTAB_SPARE$                RAW                                2000 YES

14 rows selected.

SQL>

{CDB|DBA|ALL|USER}_BLOCKCHAIN_TABLES 视图展示区块链表的信息。这些视图都基于基表SYS.BLOCKCHAIN_TABLE$。

column row_retention format a13
column row_retention_locked format a20
column table_inactivity_retention format a26
column hash_algorithm format a14

SELECT row_retention,
       row_retention_locked, 
       table_inactivity_retention,
       hash_algorithm  
FROM   user_blockchain_tables 
WHERE  table_name = 'BCT_T1';

ROW_RETENTION ROW_RETENTION_LOCKED TABLE_INACTIVITY_RETENTION HASH_ALGORITHM
------------- -------------------- -------------------------- --------------
           16 NO                                            0 SHA2_512

SQL>

修改区块链表

文档中说 NO DROP 选项可以被 ALTER TABLE 命令修改只要保留的时间不减少。但是当表初始化创建时指定NO DROP UNTIL 0 DAYS IDLE就不有效了,所有指定的值都会被返回错误。 我们现在有一张保留时间为0天的表,在下面的例子中我们尝试去修改它的保留时间到100天,然后它报错了。这个命令是格式上正确,所以我猜测是一个当前版本的bug。这个bug在19.12依然存在,不过在21.3被修复了。

alter table bct_t1 no drop until 100 days idle;

Error report -
ORA-05732: retention value cannot be lowered

SQL>

这个命令在 NO DROP UNTIL 1 DAYS IDLE或更高的时候正常。.

无论当前的延迟删除设置,尝试修改NO DROP到最大都会导致ORA-00600的错误。这个bug在19.12依然存在,不过在21.3被修复了。

alter table bct_t1 no drop;

Error starting at line : 1 in command -
alter table bct_t1 no drop
Error report -
ORA-00600: internal error code, arguments: [atbbctable_1], [0], [], [], [], [], [], [], [], [], [], []

这个问题,我估计大部分人是想安全的使用,先设置一个初始值0天,一旦他们喜欢这个设置,再增加保留时间。试用时直接使用NO DROP看起来是个十分冒险,因为唯一移除这张表的办法就是删除整个schema。

假设它没有被设定为locked。NO DELETE选项的时间可以被用ALTER TABLE 命令增加。我们当前是一行保留16天。在下面的例子中,我们将时间设置到32天。随后我们在尝试缩小到16天,他会报错。

-- Increase to 32 days.
alter table bct_t1 no delete until 32 days after insert;

Table BCT_T1 altered.

SQL>


-- Decrease to 16 days (fail).
alter table bct_t1 no delete until 16 days after insert;

Error report -
ORA-05732: retention value cannot be lowered

SQL>

在当前的版本中,尝试设置行保留时间到 NO DELETE即增加保留时间会导致ORA-00600 错误。我人为这是一个当前版本的bug。这个bug在19.12依然存在,不过在21.3被修复了。

alter table bct_t1 no delete;

Error report -
ORA-00600: internal error code, arguments: [atbbctable_1], [0], [], [], [], [], [], [], [], [], [], []

阻止dml和ddl操作

就跟我们想要的仅插入表一样,区块链表中所有DML和DDL操作,导致都行修正或删除的都会被阻止。

下面就是一个成功插入的例子,和一些不成功的DML语句。

-- INSERT
insert into bct_t1 (id, fruit, quantity, created_date ) values (1, 'apple', 20, sysdate);

1 row inserted.

SQL> commit;

Commit complete.

SQL>


-- UPDATE
update bct_t1 set quantity = 10 where id = 1;

Error report -
SQL Error: ORA-05715: operation not allowed on the blockchain table

SQL>


-- DELETE
delete from bct_t1 where id = 1;

Error report -
SQL Error: ORA-05715: operation not allowed on the blockchain table

SQL>

一些DDL语句可以修改数据内容的也会被阻止。这里有一个truncate语句的例子。

truncate table bct_t1;

Error report -
ORA-05715: operation not allowed on the blockchain table

SQL>

扩容已有列的长度是被允许的,不过增加新列或删除已有的列则不被允许。

-- Extend column.
alter table bct_t1 modify (fruit varchar2(25));

Table BCT_T1 altered.

SQL>


-- Add column
alter table bct_t1 add (additional_info varchar2(50));

Error report -
ORA-05715: operation not allowed on the blockchain table

SQL>


-- Drop column.
alter table bct_t1 drop column quantity;

Error report -
ORA-05715: operation not allowed on the blockchain table

SQL>

DBMS_BLOCKCHAIN_TABLE包
 

 DBMS_BLOCKCHAIN_TABLE 包用于维护区块链表。

 DELETE_EXPIRED_ROWS 过程删除超出保留时间的行。他们不能被delete语句删除。

set serveroutput on
declare
  l_rows  number;
begin
  dbms_blockchain_table.delete_expired_rows(
    schema_name            => 'admin',
    table_name             => 'bct_t1',
    before_timestamp       => null,
    number_of_rows_deleted => l_rows);

  dbms_output.put_line('Rows Deleted=' || l_rows);
end;
/
Rows Deleted=0

PL/SQL procedure successfully completed.

SQL>

我们也可以限制删除的日期。数据行只会删除保留时间外的,符合时间标准的。

set serveroutput on
declare
  l_rows  number;
begin
  dbms_blockchain_table.delete_expired_rows(
    schema_name            => 'testuser1',
    table_name             => 'it_t1',
    before_timestamp       => systimestamp - 60,
    number_of_rows_deleted => l_rows);

  dbms_output.put_line('Rows Deleted=' || l_rows);
end;
/
Rows Deleted=0

PL/SQL procedure successfully completed.

SQL>

VERIFY_ROWS procedure过程检查行数据和它的hash是否一致,然后签字确认。

set serveroutput on
declare
  l_rows      number;
  l_verified  number;
begin
  select count(*)
  into   l_rows
  from   admin.bct_t1;

  dbms_blockchain_table.verify_rows(
    schema_name             => 'admin',
    table_name              => 'bct_t1',
    number_of_rows_verified => l_verified);

  dbms_output.put_line('Rows=' || l_rows || '  Verified Rows=' || l_verified);
end;
/
Rows=1  Verified Rows=1

PL/SQL procedure successfully completed.

SQL>

一些思考

当你使用区块链表,这里有很多的事情需要考虑。

  • 在21.3版本前实现的版本的感觉有些。甚至在19.12的版本都在19c中有一些bug。 文档里说的有一些特性不能用,输出错误信息不准确,或捕获的不合适。这里还有一些特性完全不能用,我就没有在这篇文章里介绍。有一个例子,导致内存失败只能用重启实例修复。我会继续回看下面几个版本,看看他是否被修复,然后直接更新在本篇文章里。 
  • 区块链表比传统的表要慢,因为它有额外的工作要做。
  • 区块链表可以用常规语法被索引和分区。
  • 这里有一些数据库泵的限制,详情见 here.
  • 这里有很多常规的区块链表限制,详情见 here.
  • Oracle建议在数据库外保存每个表当前的hash值和对应的序列值。这样可以允许你对比你的记录作为额外保险。
  • 在dataguard环境中,oracle建议在使用区块链表时使用最大保护模式或者最高可用模式。
  • 用户认证可以被添加到数据中,用  DBMS_USER_CERTS包的ADD_CERTIFICATE 过程添加认证,然后再现有行里使用DBMS_BLOCKCHAIN_TABLE 包 SIGN_ROW 过程 进行认证。不过这个特性当下看起来没有效果。

我以为关键的问题在于,为什么要用区块链表

  • 如果你需要一个仅插入的防篡改表,这个会是一个解决方案。
  • 如果你想以集中的方式利用与区块链相关的信任,而不是让多个客户端应用程序单独管理区块链。使用区块链表可以集中这种信任。
  • 您可以将与区块链相关的信任添加到现有的应用程序中,而不必担心重新编码。

翻译员碎碎念:这个特性起名就很有蹭热度的意思,区块链的分权思想没有看到,更多是以保护区块链数据为目的的防篡改设计。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值