Oracle 12cR2新特性-跨容器DML(insert into container)

版权声明:本文为Buddy Yuan原创文章,未经允许不得转载。原文地址:Oracle 12cR2新特性-跨容器DML(insert into container)
 
Oracle在12c推出了多租户的概念,那么在CDB里面,怎么对PDB进行事务呢?我们一般会创建DB_LINK,而如果你不想创建DB_LINK,可以使用另外一种办法就是跨容器的DML(insert into container),该功能非常有用,可以避免创建DB_LINK,在做事务操作的时候系统会自动打开一个Link,当你退出会话的时候,打开的link就会随着消失。我们来看一下这个功能。

这是我的CDB,下面有一个PDB叫ORCLPDB1.

SQL> show pdbs;
    CON_ID CON_NAME                       OPEN MODE  RESTRICTED
---------- ------------------------------ ---------- ----------
         2 PDB$SEED                       READ ONLY  NO
         3 ORCLPDB1                       READ WRITE NO

我在ORCLPDB1中先要创建test1表用作测试。

SQL> connect sys/oracle@//localhost/ORCLPDB1  as sysdba
Connected.

SQL> create table test1 (key number primary key, value varchar2(90));
Table created.

然后我连接到CDB$ROOT开始一个事务,然后检查容器中事务的情况,由于是我开启后,没有做任何DML,因此这里没有查到任何事务。

SQL> connect sys/oracle@//localhost/ORCLCDB as sysdba
Connected.

SQL> show con_name
CON_NAME
------------------------------
CDB$ROOT

SQL> set transaction name 'Buddy';
Transaction set.

SQL> select con_id,addr,xidusn,ubafil,ses_addr,ptx_xid,name,used_urec from containers(v$transaction);
no rows selected

接下来我来执行跨容器的DML,使用insert into container()语法,注意这里需要指明容器的ID。

SQL> insert into containers(test1) (con_id,key,value) values (3,1,'Buddy Test');
1 row created.

SQL> select con_id,addr,xidusn,ubafil,ses_addr,ptx_xid,name,used_urec from containers(v$transaction);

    CON_ID ADDR                 XIDUSN     UBAFIL SES_ADDR         PTX_XID          NAME                  USED_UREC
---------- ---------------- ---------- ---------- ---------------- ---------------- -------------------- ----------
         1 000000006881E0C0          5          0 000000006DFB01F0 0000000000000000 Buddy                         1
         3 0000000068914258          3         11 000000006DFC36B0 0000000000000000                               2

这里可以看到,我开启了两个事务,一个是在容器1,也就是CDB$root下,另外一个是容器3,在ORCLPDB1里面。然后我查询事务相关的会话,我们可以发现,容器1当中的会话sqlplus也就是我现在正在执行事务的会话,而在容器3,也开启了一个会话。是系统自动开启的。

SQL> select taddr,con_id,program,action,module from v$session where saddr in (select ses_addr from v$transaction);

TADDR                CON_ID PROGRAM                                  ACTION               MODULE
---------------- ---------- ---------------------------------------- -------------------- ----------------------------------------
0000000068914258          3 oracle@oracle-18c-vagrant (TNS V1-V3)                         oracle@oracle-18c-vagrant (TNS V1-V3)
000000006881E0C0          1 sqlplus@oracle-18c-vagrant (TNS V1-V3)                        sqlplus@oracle-18c-vagrant (TNS V1-V3)

此时我们在查一下v$dblink,可以看到系统自动打开了一个db_link,而这个DB_LINK的IN_TRANSACTION是yes的。也就是说刚刚的dblink做了事务操作。

SQL> select * from v$dblink;

DB_LINK                          OWNER_ID LOG HET PROTOC OPEN_CURSORS IN_ UPD COMMIT_POINT_STRENGTH     CON_ID
------------------------------ ---------- --- --- ------ ------------ --- --- --------------------- ----------
ORCLPDB1                                0 YES YES UNKN              0 YES YES                     1          1

我们当前的事务并未提交,我们使用containers语法查询数据的时候,不会看到这条未提交的数据。这是因为这个时候会话并没有使用数据库链接去查询,而是通过切换容器来查询的。这意味着不是在同一个事务中,因此我们没看到插入的数据。

SQL> select * from containers(test1);
no rows selected

当我们执行提交。此时db_link链接还在,而IN_TRANSACTION已经变成了false。因为刚刚提交了事务,在容器3产生的会话也已经消失了。

SQL> commit;
Commit complete.

SQL> select * from v$dblink;
DB_LINK                OWNER_ID LOG HET PROTOC OPEN_CURSORS IN_ UPD COMMIT_POINT_STRENGTH     CON_ID
-------------------- ---------- --- --- ------ ------------ --- --- --------------------- ----------
ORCLPDB1                      0 YES YES UNKN              0 NO  NO                      1          1

SQL> select taddr,con_id,program,action,module from v$session where saddr in (select ses_addr from v$transaction);
no rows selected

此时再执行刚刚的容器查询,就能够查看到刚刚插入的数据了。

SQL> select * from containers(test1);

       KEY VALUE                                                                                          CON_ID
---------- ------------------------------------------------------------------------------------------ ----------
         1 Buddy Test                                                                                          3

而当我们退出sqlplus,再次登陆,查看v$dblink的时候,可以看到之前的dblink伴随这session已经消失了。
对于CDB的管理员来说,这是一个在不同的PDB里面执行DML然后却又不用创建DB_LINK的一种方式。非常的方便。

关注dbDao.com的新浪微博

扫码加入微信Oracle小密圈,了解Oracle最新技术下载分享资源

TEL/電話+86 13764045638
Email service@parnassusdata.com
QQ 47079569