版权声明:本文为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的一种方式。非常的方便。
Post a Comment