且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

[0301]Temporary Tables and RedoUndo 2

更新时间:2022-09-13 10:31:42

[20150301]Temporary Tables and RedoUndo.txt 2.txt

摘要:
Apress.Oracle.Database.Transactions.and.Locking.Revealed.1484207610.pdf

Temporary tables generate no redo for their blocks. Therefore, an operation on a temporary table is not recoverable.
When you modify a block in a temporary table, no record of this change will be made in the redo log files. However,
temporary tables do generate undo, and the undo is logged. Hence, temporary tables will generate some redo. At first
glance, this doesn't seem to make total sense: Why would they need to generate undo? This is because you can roll
back to a SAVEPOINT within a transaction. You might erase the last 50 INSERTs into a temporary table, leaving the first 50.
Temporary tables can have constraints and everything else a normal table can have. They might fail a statement on
the five-hundredth row of a 500-row INSERT, necessitating a rollback of that statement. Since temporary tables behave
in general just like normal tables, temporary tables must generate undo. Since undo data must be logged, temporary
tables will generate some redo log for the undo they generate.

This is not nearly as ominous as it seems. The primary SQL statements used against temporary tables are INSERTs
and SELECTs. Fortunately, INSERTs generate very little undo (you need to restore the block to "nothing," and it doesn't
take very much room to store "nothing"), and SELECTs generate no undo. Hence, if you use temporary tables for
INSERTs and SELECTs exclusively, this section means nothing to you. It is only if you UPDATE or DELETE that you might
be concerned about this.

I set up a small test to demonstrate the amount of redo generated while working with temporary tables, an
indication therefore of the amount of undo generated for temporary tables, since only the undo is logged for them. To
demonstrate, I'll take identically configured permanent and temporary tables, and then perform the same operations
on each, measuring the amount of redo generated each time. The tables I'll use are as follows:

1.建立测试环境:

SCOTT@test01p> @ver1

PORT_STRING                    VERSION        BANNER                                                                               CON_ID
------------------------------ -------------- -------------------------------------------------------------------------------- ----------
IBMPC/WIN_NT64-9.1.0           12.1.0.1.0     Oracle Database 12c Enterprise Edition Release 12.1.0.1.0 - 64bit Production              0

--12c 加入了temp_undo_enabled 参数,可以把临时表的产生的undo放在临时表空间.缺省设置是false.

create table perm( x char(2000) ,  y char(2000) ,  z char(2000)  );
create global temporary table temp ( x char(2000) , y char(2000) , z char(2000)  ) on commit preserve rows;

create or replace function get_stat_val( p_name in varchar2 ) return number
as
l_val number;
begin
    select b.value into l_val from v$statname a, v$mystat b where a.statistic# = b.statistic# and a.name = p_name; return l_val;
end;

create or replace procedure do_sql( p_sql in varchar2 )
as
    l_start_redo    number;
    l_redo            number;
begin
    l_start_redo := get_stat_val( 'redo size' );

    execute immediate p_sql;
    commit;

    l_redo := get_stat_val( 'redo size' ) - l_start_redo;

    dbms_output.put_line
    ( to_char(l_redo,'99,999,999') ||' bytes of redo generated for "' ||
      substr( replace( p_sql, chr(10), ' '), 1, 25 ) || '"...' );
end;
/

2.开始测试:
set serveroutput on format wrapped
alter session set temp_undo_enabled=true;
begin
    do_sql( 'insert into perm
             select 1,1,1
               from all_objects
              where rownum

    do_sql( 'insert into temp
             select 1,1,1
               from all_objects
              where rownum     dbms_output.new_line;

    do_sql( 'update perm set x = 2' );
    do_sql( 'update temp set x = 2' );
    dbms_output.new_line;

    do_sql( 'delete from perm' );
    do_sql( 'delete from temp' );
end;
/
3,259,344 bytes of redo generated for "insert into perm         "...
536 bytes of redo generated for "insert into temp         "...
2,179,232 bytes of redo generated for "update perm set x = 2"...
536 bytes of redo generated for "update temp set x = 2"...
3,244,248 bytes of redo generated for "delete from perm"...
536 bytes of redo generated for "delete from temp"...

PL/SQL procedure successfully completed.

--可以发现生成的redo都是一样的.不论是insert,update,delete. 不像11g的情况.

--摘要:Apress.Oracle.Database.Transactions.and.Locking.Revealed.1484207610.pdf P153

Starting with Oracle12c, in an Oracle Active Data Guard configuration, you can issue DML statements directly on
a temporary table that exists in a standby database. We can view the amount of redo generated for a temporary table
in a standby database by running the same code (from the "Prior to 12c" section) against a standby database. The only
difference being the statements issuing transactions against permanent tables must be removed (because you cannot
issue DML on a permanent table in a standby database). Here is the output showing that 0 bytes of redo are generated:
0 bytes of redo generated for "insert into temp"...
0 bytes of redo generated for "update temp set x = 2"...
0 bytes of redo generated for "delete from temp"...

■ Note there's no need to set TEMP_UNDO_ENABLED in the standby database. this is because temporary undo is always
enabled in an Oracle active data guard standby database.
--好改进,有机会测试看看,没有做过12c的dataguard.

Global temporary tables are often used for reporting purposes—like generating and storing intermediate query
results. Oracle Active Data Guard is often used to offload reporting applications to the standby database. Couple
global temporary tables with Oracle Active Data Guard, and you have a more powerful tool to address your reporting
requirements.
--而且这样可以改进一些报表的处理。

3.看看一些细节:
SCOTT@test01p> alter session set temp_undo_enabled=true;
Session altered.

SCOTT@test01p> insert into temp select 1,1,1 from all_objects where rownum 2 rows created.

SCOTT@test01p> @xid
X
------------------------------
10.11.6462

    XIDUSN    XIDSLOT     XIDSQN     UBAFIL     UBABLK     UBAREC     UBASQN STATUS            USED_UBLK  USED_UREC XID              ADDR
---------- ---------- ---------- ---------- ---------- ---------- ---------- ---------------- ---------- ---------- ---------------- ----------------
        10         11       6462          0          0          0          0 ACTIVE                    1          1 0A000B003E190000 000007FF5EA2B4D8

--UBAFILE是0.

SCOTT@test01p> select rowid from temp ;
ROWID
------------------
AAQL8HAABAAAL8IAAA
AAQL8HAABAAAL8JAAA

SCOTT@test01p> @lookup_rowid AAQL8HAABAAAL8IAAA
    OBJECT       FILE      BLOCK        ROW DBA                  TEXT
---------- ---------- ---------- ---------- -------------------- ----------------------------------------
   4243207          1      48904          0 1,48904              alter system dump datafile 1 block 48904

--先放弃,有机会再研究看看。