暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Oracle Database 21c新特性讲座(5)——区块链表、设定表空间的默认加密算法、使用Database Vault

甲骨文云技术 2020-12-31
974

这是Oracle Database 21c新特性讲座的第5讲,也是本实验讲座的最后一讲,在今天的内容中将为大家介绍区块链表、表空间加密算法与Database Vault。

实验5-1:区块链表

区块链表在Oracle Database 20c当中就为大家提供了,关于它的详细介绍可以参考如Oracle Database 20c:区块链表,在今天的实验中,我们通过例子为大家复习一遍。

我们在auditor用户下面创建一个区块链表AUDITOR.LEDGER_EMP,用它来记录HR.EMPLOYEES表的变化。大家他用过观察下面的建表语句可以知道,这个表除非31天没有更新,否则不能被删除,表中的数据也不能被删除。需要注意的是,当前版本中,表的保存时间至少为16天。

    SQL> CREATE BLOCKCHAIN TABLE ledger_emp (employee_id NUMBER, salary NUMBER)
    2 NO DROP UNTIL 31 DAYS IDLE
    3 NO DELETE LOCKED
    4 HASHING USING "SHA2_512" VERSION "v1";

    Table created.

    SQL>

    可以通过数据字典user_blockchain_tables查询区块链表的信息。可以通过user_tab_cols查询区块链表内部用于记录的详细字段信息。

      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>
      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
      12 ORABCTAB_SPARE$ RAW 2000

      12 rows selected.

      SQL>

      接下来我们使用不同的用户向区块链表中写入数据,然后通过数据字典查看一下内部的记录情况。

        [oracle@henry ~]$ sqlplus auditor@pdb1

        SQL*Plus: Release 21.0.0.0.0 - Production on Mon Dec 28 04:15:59 2020
        Version 21.1.0.0.0

        Copyright (c) 1982, 2020, Oracle. All rights reserved.

        Enter password:
        Last Successful login time: Mon Dec 28 2020 04:04:35 +00:00

        Connected to:
        Oracle Database 21c EE High Perf Release 21.0.0.0.0 - Production
        Version 21.1.0.0.0

        SQL> INSERT INTO ledger_emp VALUES (106,12000);

        1 row created.

        SQL> commit;

        Commit complete.

        SQL>

        我们刚才使用auditor用户登录并插入数据,我们看看数据字典当中是如何记录的。我们看到User Num对应的数值是121.

          ELECT 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;

          上面看到的121对应着V$session当中的user#,通过下面的查询,我们可以看到上面区块链表中的记录是AUDITOR用户插入的。

            SQL> select user#,username from v$session where user#=121;

            USER# USERNAME
            ---------- ----------------------------------------
            121 AUDITOR

            接下来我们换hr用户对这个区块链表插入记录,然后再使用上面的SQL语句查询数据字典,来了解区块链变内部的记录变化。

              [oracle@henry ~]$ sqlplus hr@pdb1

              SQL*Plus: Release 21.0.0.0.0 - Production on Mon Dec 28 04:37:17 2020
              Version 21.1.0.0.0

              Copyright (c) 1982, 2020, Oracle. All rights reserved.

              Enter password:
              Last Successful login time: Mon Dec 28 2020 04:36:36 +00:00

              Connected to:
              Oracle Database 21c EE High Perf Release 21.0.0.0.0 - Production
              Version 21.1.0.0.0

              SQL> INSERT INTO auditor.ledger_emp VALUES (106,24000);

              1 row created.

              SQL> commit;

              Commit complete.

              SQL>

              接下来我们通过数据字典查看一下区块链表的变化。我们发现多了一条记录,并且user num是119.

              我们通过v$session查询这个119是谁。

                SQL> select user#,username from v$session where user#=119;

                USER# USERNAME
                ---------- ----------------------------------------
                       119 HR


                在我们介绍20c新特性的时候,介绍到区块链表的记录删除规则,如果我们在创建区块链表的时候,设定了表中记录可以在特定条件下删除,那么当条件满足时,是可以删除的(可以参考:Oracle Database 20c:区块链表中的介绍)。

                下面我们对刚才创建的区块链表中的记录进行删除操作。我们使用delete语句删除记录的时候,会收到如下报错信息ORA-5717,通过oerr查询,可以看到具体的错误原因及解决方案。因为刚才的操作就是不被允许的,所以对应的Action是no action requitd.

                  [oracle@henry ~]$ sqlplus auditor@pdb1

                  SQL*Plus: Release 21.0.0.0.0 - Production on Mon Dec 28 04:57:34 2020
                  Version 21.1.0.0.0

                  Copyright (c) 1982, 2020, Oracle. All rights reserved.

                  Enter password:
                  Last Successful login time: Mon Dec 28 2020 04:25:26 +00:00

                  Connected to:
                  Oracle Database 21c EE High Perf Release 21.0.0.0.0 - Production
                  Version 21.1.0.0.0

                  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


                  SQL>

                  [oracle@henry ~]$ oerr ora 5715
                  05715, 0000, "operation not allowed on the blockchain table"
                  // *Cause: The table was insert-only table and, therefore, could not be
                  // updated or deleted.
                  //
                  // *Action: No action required.
                  //
                  [oracle@henry ~]$


                  如果想删除区块链表中满足删除条件的记录,要使用BLOCKCHAIN_TABLE.DELETE_EXPIRED_ROWS这个存储过程来完成。下面我们就使用它对表中的数据进行删除,但因为这个表中的记录是刚创建的,不满足删除条件,所以最后的输出结果是0条记录被删除。需要注意的是如果是在20c当中,使用的删除记录存储过程是:DBMS_BLOCKCHAIN_TABLE.DELETE_ROWS。

                    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.

                    SQL>

                    关于表的drop,区块链表在特定条件下是可以被drop的,以我们刚刚创建的区块链表为例,我们在创建的时候设定了如果这个区块链表31天处于非活动状态,那么这个表就可以被drop掉了。因为当前不满足删除条件,所以使用drop语句的时候,会报如下错误。

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


                      接下来我们可以通过存储过程DBMS_BLOCKCHAIN_TABLE.VERIFY_ROWS来验证区块链表中的数据有效性。

                        SQL> DECLARE
                        2 row_count NUMBER;
                        3 verify_rows NUMBER;
                        4 instance_id NUMBER;
                        5 BEGIN
                        6 FOR instance_id IN 1 .. 2 LOOP
                        7 SELECT COUNT(*) INTO row_count FROM auditor.ledger_emp WHERE ORABCTAB_INST_ID$=instance_id;
                        8 DBMS_BLOCKCHAIN_TABLE.VERIFY_ROWS('AUDITOR','LEDGER_EMP', NULL, NULL, instance_id, NULL, verify_rows);
                        9 DBMS_OUTPUT.PUT_LINE('Number of rows verified in instance Id '|| instance_id || ' = '|| row_count);
                        10 END LOOP;
                        11 END;
                        12
                        Number of rows verified in instance Id 1 = 2
                        Number of rows verified in instance Id 2 = 0

                        PL/SQL procedure successfully completed.

                        SQL>

                        实验5-2:设定表空间的默认加密算法

                        我们首先查询一下当前的默认表空间加密算法。

                          SQL> SHOW PARAMETER TABLESPACE_ENCRYPTION_DEFAULT_ALGORITHM

                          NAME TYPE VALUE
                          ------------------------------------ ----------- ------------------------------
                          tablespace_encryption_default_algori string AES128
                          thm
                          SQL>

                          接下来我们将系统的表空间默认加密算法改成AES192,然后创建一个新的表空间,看看是否生效。通过观察发现,之前创建的表空间的加密算法为AES128,而新创建的表空间加密算法为AES192.

                            SQL> ALTER SYSTEM SET TABLESPACE_ENCRYPTION_DEFAULT_ALGORITHM=AES192;

                            System altered.

                            SQL>
                            SQL> CREATE TABLESPACE tbstest DATAFILE '/u02/app/oracle/oradata/DB21C_ICN1B6/test01.dbf' SIZE 2M;

                            Tablespace created.

                            SQL> SELECT name, encryptionalg FROM v$tablespace t, v$encrypted_tablespaces v WHERE t.ts#=v.ts#;

                            NAME ENCRYPT
                            ------------------------------ -------
                            USERS AES128
                            USERS1 AES128
                            USERS2 AES128
                            LEDGERTBS AES128
                            TBSTEST AES192

                            实验5-3:使用Database Vault

                            数据库堡垒在Oracle早期的版本当中就为大家提供了,记得十年前为一个客户onsite授课的时候,先坐国际航班然后转国内航班,再转机场巴士,然后是计程车,最后乘坐三轮车到达客户现场,现在想起来都觉得是一段很神奇的经历。

                            数据库堡垒,我们通常叫做DV,可以严格限制数据库中的数据访问,权限设置非常灵活,在广大的司法、公安、金融等对数据防止篡改和防止越权访问的客户中广泛被应用。DV在Oracle Database 21c当中也有了很多增强。

                            我们用管理账户登录,查看一下当前DV_ALLOW_COMMON_OPERATION的状态。当前状态为False,没有进行访问保护。

                              [oracle@henry ~]$ sqlplus c##sec_admin

                              SQL*Plus: Release 21.0.0.0.0 - Production on Mon Dec 28 06:08:54 2020
                              Version 21.1.0.0.0

                              Copyright (c) 1982, 2020, Oracle. All rights reserved.

                              Enter password:
                              Last Successful login time: Mon Dec 28 2020 05:34:04 +00:00

                              Connected to:
                              Oracle Database 21c EE High Perf Release 21.0.0.0.0 - Production
                              Version 21.1.0.0.0

                              SQL> SELECT * FROM DVSYS.DBA_DV_COMMON_OPERATION_STATUS;

                              NAME STATU
                              ------------------------- -----
                              DV_ALLOW_COMMON_OPERATION FALSE

                              首先我们测试一下,在没有设定访问规则的时候的用户访问数据情况。我们有两个CDB上的common user:c##test1和c##test2,在c##test1下面有两张表,一个是在CDB全局访问的g_emp另外一个是在PDB本地访问的l_emp。我们通过授权让c##test2用户可以访问当这两张表,g_emp和l_emp。观察下方输出,c##test1和c##test2这两个用户对于c##test1.g_emp这个全局表都可以访问。

                                SQL> CONNECT c##test1
                                Enter password:
                                Connected.
                                SQL> SELECT * FROM c##test1.g_emp;

                                NAME SALARY
                                ---------- ----------
                                EMP_GLOBAL 1000

                                SQL> CONNECT c##test2
                                Enter password:
                                Connected.
                                SQL> SELECT * FROM c##test1.g_emp;

                                NAME SALARY
                                ---------- ----------
                                EMP_GLOBAL 1000

                                接下来使用c##test1和c##test2查询位于pdb上面的l_emp表。发现这两个用户都可以访问。

                                  SQL> CONNECT c##test1@pdb1
                                  Enter password:
                                  Connected.
                                  SQL> SELECT * FROM c##test1.l_emp;

                                  NAME SALARY
                                  ---------- ----------
                                  EMP_LOCAL 2000

                                  SQL> CONNECT c##test2@pdb1
                                  Enter password:
                                  Connected.
                                  SQL> SELECT * FROM c##test1.l_emp;

                                  NAME SALARY
                                  ---------- ----------
                                  EMP_LOCAL 2000


                                  接下来我们设定在common object上使用公共规则或强制域,测试表数据可访问性。首先使用DV管理用户登录CDB并创建访问规则,这个规则用于保护CDB上的数据表(当前例子中的g_emp),创建规则之后,将受保护的对象加入这个规则当中。关于DV的详细说明,大家可以参考docs.oracle.com中的解释。

                                    [oracle@henry ~]$ sqlplus c##sec_admin

                                    SQL*Plus: Release 21.0.0.0.0 - Production on Mon Dec 28 06:21:21 2020
                                    Version 21.1.0.0.0

                                    Copyright (c) 1982, 2020, Oracle. All rights reserved.

                                    Enter password:
                                    Last Successful login time: Mon Dec 28 2020 06:08:58 +00:00

                                    Connected to:
                                    Oracle Database 21c EE High Perf Release 21.0.0.0.0 - Production
                                    Version 21.1.0.0.0

                                    SQL> BEGIN
                                    DBMS_MACADM.CREATE_REALM(
                                    realm_name => 'Root Test Realm',
                                    description => 'Test Realm description',
                                    enabled => DBMS_MACUTL.G_YES,
                                    audit_options => DBMS_MACUTL.G_REALM_AUDIT_FAIL,
                                    realm_type => 0);
                                    END;
                                    /

                                    PL/SQL procedure successfully completed.
                                    SQL> BEGIN
                                    DBMS_MACADM.ADD_OBJECT_TO_REALM(
                                    realm_name => 'Root Test Realm',
                                    object_owner => 'C##TEST1',
                                    object_name => '%',
                                    object_type => '%');
                                    END;
                                    /

                                    PL/SQL procedure successfully completed.


                                    现在使用c##test1和c##test2登录,来访问在CDB当中的g_emp。发现c##test2已经无法访问原来可以访问的g_emp,即便它有DBA权限。

                                      SQL> CONNECT c##test1
                                      Enter password:
                                      Connected.
                                      SQL> SELECT * FROM c##test1.g_emp;

                                      NAME SALARY
                                      ---------- ----------
                                      EMP_GLOBAL 1000

                                      SQL> CONNECT c##test2
                                      Enter password:
                                      Connected.
                                      SQL> SELECT * FROM c##test1.g_emp;
                                      SELECT * FROM c##test1.g_emp
                                      *
                                      ERROR at line 1:
                                      ORA-01031: insufficient privileges

                                      接下来我们看看pdb1当中的l_emp都否可以被两个用户访问。通过观察c##test2用户因为有DBA权限,依旧可以访问pdb1上的c##test1下面的表l_emp。

                                        SQL> CONNECT c##test1@pdb1
                                        Enter password:
                                        Connected.
                                        SQL> SELECT * FROM c##test1.l_emp;

                                        NAME SALARY
                                        ---------- ----------
                                        EMP_LOCAL 2000

                                        SQL> CONNECT c##test2@pdb1
                                        Enter password:
                                        Connected.
                                        SQL> SELECT * FROM c##test1.l_emp;

                                        NAME SALARY
                                        ---------- ----------
                                        EMP_LOCAL 2000

                                        我们现在将刚才创建的realm删除,重现在CDB级别创建一个realm,只不过要将realm_type由原来的0改成1,然后看看效果。

                                          SQL> CONNECT c##sec_admin
                                          Enter password:
                                          Connected.
                                          SQL> EXEC DBMS_MACADM.DELETE_REALM_CASCADE('Root Test Realm')

                                          PL/SQL procedure successfully completed.

                                          SQL> BEGIN
                                          DBMS_MACADM.CREATE_REALM(
                                          realm_name => 'Root Test Realm',
                                          description => 'Test Realm description',
                                          enabled => DBMS_MACUTL.G_YES,
                                          audit_options => DBMS_MACUTL.G_REALM_AUDIT_FAIL,
                                          realm_type => 1);
                                          END;
                                          /

                                          PL/SQL procedure successfully completed.

                                          SQL> BEGIN
                                          DBMS_MACADM.ADD_OBJECT_TO_REALM(
                                          realm_name => 'Root Test Realm',
                                          object_owner => 'C##TEST1',
                                          object_name => '%',
                                          object_type => '%');
                                          END;
                                          /

                                          PL/SQL procedure successfully completed.

                                          我们依旧使用上面的登录方式做相同的访问。发现CDB当中的g_emp即便是它的owner也无法访问了,关于创建realm的参数配置,大家去参考docs.oracle.com官方文档即可。

                                            SQL> CONNECT c##test1
                                            Enter password:
                                            Connected.
                                            SQL> SELECT * FROM c##test1.g_emp;
                                            SELECT * FROM c##test1.g_emp
                                            *
                                            ERROR at line 1:
                                            ORA-01031: insufficient privileges


                                            SQL> CONNECT c##test2
                                            Enter password:
                                            Connected.
                                            SQL> SELECT * FROM c##test1.g_emp;
                                            SELECT * FROM c##test1.g_emp
                                            *
                                            ERROR at line 1:
                                            ORA-01031: insufficient privileges

                                            接下来使用这两个common user查询pdb1上的l_emp,都可以访问。因为刚才创建的realm是针对容器数据库的。为了后面的实验,我们将刚才创建的realm删除掉。

                                              SQL> CONNECT c##test1@pdb1
                                              Enter password:
                                              Connected.
                                              SQL> SELECT * FROM c##test1.l_emp;

                                              NAME SALARY
                                              ---------- ----------
                                              EMP_LOCAL 2000
                                              SQL> CONNECT c##test2@pdb1
                                              Enter password:
                                              Connected.
                                              SQL> SELECT * FROM c##test1.l_emp;

                                              NAME SALARY
                                              ---------- ----------
                                              EMP_LOCAL 2000

                                              SQL> CONNECT c##sec_admin
                                              Enter password:
                                              Connected.
                                              SQL> EXEC DBMS_MACADM.DELETE_REALM_CASCADE('Root Test Realm')

                                              PL/SQL procedure successfully completed.

                                              接下来我们测试使用PDB规则域或强制域测试普通对象上的表数据可访问性。与上面一样,我们首先创建realm规则,然后将C##test1的对象添加到规则当中。

                                                SQL> CONNECT c##sec_admin
                                                Enter password:
                                                Connected.
                                                SQL> EXEC DBMS_MACADM.DELETE_REALM_CASCADE('Root Test Realm')

                                                PL/SQL procedure successfully completed.

                                                SQL> CONNECT sec_admin@pdb1
                                                Enter password:
                                                Connected.
                                                SQL> BEGIN
                                                DBMS_MACADM.CREATE_REALM(
                                                realm_name => 'Test Realm',
                                                description => 'Test Realm description',
                                                enabled => DBMS_MACUTL.G_YES,
                                                audit_options => DBMS_MACUTL.G_REALM_AUDIT_FAIL,
                                                realm_type => 0);
                                                END;
                                                /

                                                PL/SQL procedure successfully completed.

                                                SQL> BEGIN
                                                DBMS_MACADM.ADD_OBJECT_TO_REALM(
                                                realm_name => 'Test Realm',
                                                object_owner => 'C##TEST1',
                                                object_name => '%',
                                                object_type => '%');
                                                END;
                                                /

                                                PL/SQL procedure successfully completed.

                                                接下来我们进行数据对象可访问性测试:首先用C##test1和C#test2访问CDB上的数据对象g_emp,因为刚刚创建realm是针对PDB进行保护的所以上面两个用户都可以访问g_emp。

                                                  SQL> CONNECT c##test1
                                                  Enter password:
                                                  Connected.
                                                  SQL> SELECT * FROM c##test1.g_emp;

                                                  NAME SALARY
                                                  ---------- ----------
                                                  EMP_GLOBAL 1000

                                                  SQL> CONNECT c##test2
                                                  Enter password:
                                                  Connected.
                                                  SQL> SELECT * FROM c##test1.g_emp;

                                                  NAME SALARY
                                                  ---------- ----------
                                                  EMP_GLOBAL 1000

                                                  SQL>

                                                  接下来测试访问在PDB当中的l_emp,C##test1还是可以访问自己的对象的,但是拥有DBA角色的C##test2无法访问其他用户下面的数据对象。

                                                    SQL> CONNECT c##test1@PDB1
                                                    Enter password:
                                                    Connected.
                                                    SQL> SELECT * FROM c##test1.l_emp;

                                                    NAME SALARY
                                                    ---------- ----------
                                                    EMP_LOCAL 2000

                                                    SQL> CONNECT c##test2@PDB1
                                                    Enter password:
                                                    Connected.
                                                    SQL> SELECT * FROM c##test1.l_emp;
                                                    SELECT * FROM c##test1.l_emp
                                                    *
                                                    ERROR at line 1:
                                                    ORA-01031: insufficient privileges


                                                    SQL>

                                                    大家可以重复上面的实验,将这个realm删除,然后创建一个realm_type=1的规则,然后将C##test1的对象添加到规则当中,然后看看访问结果是怎样。

                                                    我们在讲解DV的开始部分,有一个参数DV_ALLOW_COMMON_OPERATION,默认是False,如果我们将它设定为True,将按照如下表格进行访问控制,我们可以通过如下代码进行修改:

                                                      SQL> CONNECT c##sec_admin
                                                      Enter password:
                                                      Connected.
                                                      SQL> SELECT * FROM DVSYS.DBA_DV_COMMON_OPERATION_STATUS;

                                                      NAME STATU
                                                      ------------------------- -----
                                                      DV_ALLOW_COMMON_OPERATION FALSE

                                                      SQL> EXEC DBMS_MACADM.ALLOW_COMMON_OPERATION

                                                      PL/SQL procedure successfully completed.

                                                      SQL> SELECT * FROM DVSYS.DBA_DV_COMMON_OPERATION_STATUS;

                                                      NAME STATU
                                                      ------------------------- -----
                                                      DV_ALLOW_COMMON_OPERATION TRUE

                                                      大家可以在修改之后,按照上面的实验进行创建realm并将对象添加到realm当中,大家自己实验的时候,向realm添加对象为什么会报错?使用oerr查询一下,原因说得很清楚。

                                                      `FALSE``TRUE`
                                                      `C##TEST1``C##TEST2``C##TEST1``C##TEST2`
                                                      Common Regular or Mandatory Realm in CDB rootNo changeNo changeNo changeNo change
                                                      PDB Regular RealmAccessBlockedAccess**Access**
                                                      PDB Mandatory RealmBlockedBlocked**Access****Access**

                                                      关于DV还有好多功能等待大家去探索,大家可以访问https://docs.oracle.com/en/database/oracle/oracle-database/21/dvadm/index.html获取更多资讯。

                                                      到这里Oracle Database 21c新特性实验教程就结束了,我们会在后面的文章中继续为大家介绍Oracle Database 21c的其他特性细节,期待您的关注。

                                                      光阴如梭,一年的工作转瞬又将成为历史,2020即将过去,2021即将来临。新的一年意味着新的起点、新的机遇、新的挑战,祝愿大家在2021,身体健康,工作顺利!

                                                      相关链接:

                                                      Oracle Database 21c新特性讲座(1)

                                                      Oracle Database 21c新特性讲座(2)

                                                      Oracle Database 21c新特性讲座(3)

                                                      Oracle Database 21c新特性讲座(4)

                                                      编辑:殷海英

                                                      最后修改时间:2020-12-31 10:47:08
                                                      文章转载自甲骨文云技术,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

                                                      评论