zoukankan      html  css  js  c++  java
  • 练习 DOUBLE INSERT

     

     练习 DOUBLE INSERT

    目标:从一张表取数据插入到另一张表中,此外需要为插入的目标表做一个应用级的日志表,也就是说在插入目标表的同时,还需要将相同的数据插入到日志表中。

    在案例一中,我们给出了CREATE TRIGGEROPEN CURSOR ;BULK INTO VARIABLE; DOUBLE INSERT; INSERT ALL 等方案。每个方案中也阐述了他的优缺点。

    其中在DOUBLE INSERT,为了保证数据的一致性,又给出了四种思路,它们分别是锁,串行,临时表和as of 查询。下面将展现这四种思路SQL的展现。

    当然DOUBLE INSERT 除了一致性的问题,还有原子性的问题,即有可有目标表 日志表只成功了其它一个,或都没成功。关于原子性的问题。暂不讨论。

     

    1.1思路一

    Drop table test;

    Drop table T_ORG;

    DROP TABLE T_LOG;

    create table test as select * from all_objects ;

    create table T_ORG as select * from all_objects  WHERE 1=2;

    create table T_LOG as select * from all_objects WHERE 1=2;

     

     

    #   --共享行专用(SRX):阻止其他事务操作,其会会话不能对test表进行DML操作

    SQL> lock table t in exclusive mode nowait;  

     

    Locked Object:

     

    OWNEROS_USER_NAME  OBJECT_NAME   SIDSERIAL# LOCKED_MODE LOGON_TIM

    ------- ------------- ----------------- ---------- ----------- -------

    SYS     oracle        TEST       18         17           6 26-APR-19

     

     

    SYS@test>INSERT INTO T_ORG SELECT * FROM TEST;

    72183 rows created.

    SYS@test>INSERT INTO T_LOG SELECT * FROM TEST;

    72183 rows created.

     

    新开一个窗口执行delete 操作产生等待:

    SYS@test2>delete from test where OBJECT_ID <10 ;  

    直到原来窗口事务结束。

    SYS@test>COMMIT ;

     

    问题:影响其它事务

     

    1.2思路二 串行事务面临的问题 ora-01555

    Drop table test;

    Drop table T_ORG;

    DROP TABLE T_LOG;

    create table test as select * from all_objects ;

    create table T_ORG as select * from all_objects  WHERE 1=2;

    create table T_LOG as select * from all_objects WHERE 1=2;

     

    SYS@test>create undo tablespace undotbs datafile '/u01/app/oracle/oradata/test/undotbs.dbf' size 1M ;

    Tablespace created.

     

    SYS@test>alter system set undo_tablespace=undotbs;

     

    SYS@test>show parameter undo ;

     

    NAME                                 TYPE        VALUE

    ------------------------------------ ----------- ---------------------

    undo_management                      string      AUTO

    undo_retention                       integer     900

    undo_tablespace                      string      UNDOTBS

     

     

    declare

    begin

    INSERT INTO T_ORG SELECT * FROM TEST;

    INSERT INTO T_LOG SELECT * FROM TEST;

    Commit ;

    end ;

    /

     

    *

    ERROR at line 1:

    ORA-30036: unable to extend segment by 8 in undo tablespace 'UNDOTBS'

    ORA-06512: at line 3

     

    SYS@test>select count(*) from T_ORG ;

      COUNT(*)

    ----------

             0

     

    问题:UNDO 空间不足时,会报ORA-30036
         
    如果UNDO空间被覆盖会报ORA-01555

     

    1.3思路三 临时表

    Drop table test;

    Drop table T_ORG;

    DROP TABLE T_LOG;

    create table test as select * from all_objects ;

    create table T_ORG as select * from all_objects  WHERE 1=2;

    create table T_LOG as select * from all_objects WHERE 1=2;

     

    SYS@test>alter system set undo_tablespace=UNDOTBS1;

     

    创建会话级别临时表:

    SYS@test> create global temporary table temp1 on Commit Preserve Rows  as select * from all_objects where 1=2   ;

     

    把数据写入到临时表:

    SYS@test>INSERT INTO temp1 SELECT * FROM all_objects;

    72186 rows created.

     

    SYS@test>INSERT INTO T_ORG SELECT * FROM temp1;

    72186 rows created.

    SYS@test>INSERT INTO T_LOG SELECT * FROM temp1;

    72186 rows created.

     

    问题:相关于写了三次,读了三次,对性能影响较大

     

    1.4思路四 AS OF 查询

    Drop table test;

    Drop table T_ORG;

    DROP TABLE T_LOG;

    create table test as select * from all_objects ;

    create table T_ORG as select * from all_objects  WHERE 1=2;

    create table T_LOG as select * from all_objects WHERE 1=2;

     

    SYS@test>select current_scn from v$database  ;

    CURRENT_SCN

    -----------

         975216

     

     

    SYS@test>INSERT INTO T_ORG SELECT * FROM test as of scn 975216;

    72184 rows created.

     

    SYS@test>INSERT INTO T_LOG SELECT * FROM test as of scn 975216;

    72184 rows created.

     

    前提是你要提前查询SCN 时间,而且还是查询插入了2次。

     

    针对以上的问题,最好的解决方案是利用ORACLE insert all

    <wiz_tmp_tag id="wiz-table-range-border" contenteditable="false" style="display: none;">





  • 相关阅读:
    Python_Note_08Day 9_HTML
    Python_Note_08Day 6_Bastion Host_Paramiko_SSH
    Python_Note_08Day 5_Module
    Python_Note_Day 11_Mysql02_Python MySQL API
    Python_Note_Day 11_Mysql
    Python_Data_Analysis_01
    485. Max Consecutive Ones
    498. Diagonal Traverse
    500. Keyboard Row
    481. Magical String
  • 原文地址:https://www.cnblogs.com/cqdba/p/bdbfe7a50561d41f8c43fb70fceecfec.html
Copyright © 2011-2022 走看看