http://blog.csdn.net/jat_chipmore/archive/2008/11/27/3391402.aspx
从理论上来说,对于 direct insert 的 undo (rowid)实在没有存在的必要
因为HWM 在移动的过程中,这些block是不能被其他process使用的,那么,意味着,只要记录下该次direct insert所涉及到的 空间的redo 和 undo ,在失败回滚的时候,只需要把这些空间修改为原来的状态就可以而而不用逐个记录去delete。
为此我将在这里做几个组合实验
SQL> select * from v$version;
BANNER
----------------------------------------------------------------
Oracle Database 10g Enterprise Edition Release 10.1.0.2.0 - Prod
PL/SQL Release 10.1.0.2.0 - Production
CORE 10.1.0.2.0 Production
TNS for Linux: Version 10.1.0.2.0 - Production
NLSRTL Version 10.1.0.2.0 - Production
SQL>
SQL> drop table t;
Table dropped.
SQL> create table t as select * from dba_objects ;
Table created.
SQL> select usn,RSSIZE ,WRITES from v$rollstat;
USN RSSIZE WRITES
---------- ---------- ----------
0 385024 7620
1 253952 11168864
2 2220032 11335220
3 2220032 9668346
4 1171456 8887572
5 122880 84154
6 122880 0
7 1171456 234
8 122880 0
9 122880 0
10 122880 0
11 rows selected.
SQL> insert into t select * from dba_objects;
13197 rows created.
SQL> commit;
Commit complete.
SQL> select usn,RSSIZE ,WRITES from v$rollstat;
USN RSSIZE WRITES
---------- ---------- ----------
0 385024 7620
1 253952 11168864
2 2220032 11336024
3 2220032 9668346
4 2220032 9810066
5 122880 85452
6 122880 0
7 1171456 234
8 122880 0
9 122880 0
10 122880 0
11 rows selected.
SQL> select 9810066 - 8887572 from dual;
9810066-8887572
---------------
922494 正常情况下产生的回滚段信息量
SQL> select 85452 - 84152 from dual;
85452-84152
-----------
1300 undo中这个细微变化目前不详,估计可能是空间的变化导致的
SQL> alter table t nologging;设置表为nologging
Table altered.
SQL> insert /*+ append */ into t select * from dba_objects; direct insert
13197 rows created.
SQL> commit;
Commit complete.
SQL> select usn,RSSIZE ,WRITES from v$rollstat;
USN RSSIZE WRITES
---------- ---------- ----------
0 385024 7620
1 253952 11169498
2 2220032 11339548
3 2220032 9670376
4 2220032 9813076
5 122880 85452
6 122880 0
7 1171456 234
8 122880 0
9 122880 0
10 122880 0
11 rows selected.
SQL> select 9670376 - 9668346 from dual;
9670376-9668346
---------------
2030 发现回滚段信息极少
SQL> select 9813076-9810066 from dual;
9813076-9810066
---------------
3010
SQL>
SQL> alter table t logging; 把表置回logging状态
Table altered.
SQL> select usn,RSSIZE ,WRITES from v$rollstat;
USN RSSIZE WRITES
---------- ---------- ----------
0 385024 7620
1 253952 11173844
2 2220032 11343052
3 2220032 9676700
4 2220032 9816500
5 122880 89668
6 122880 0
7 1171456 234
8 122880 0
9 122880 0
10 122880 0
11 rows selected.
SQL> insert into t select * from dba_objects; 正常插入数据
13197 rows created.
SQL> commit;
Commit complete.
SQL> select usn,RSSIZE ,WRITES from v$rollstat;
USN RSSIZE WRITES
---------- ---------- ----------
0 385024 7620
1 253952 11173844
2 2220032 12266342
3 2220032 9676918
4 2220032 9817356
5 122880 90478
6 122880 0
7 1171456 234
8 122880 0
9 122880 0
10 122880 0
11 rows selected.
SQL> select 12266342 - 11343052 from dual;
12266342-11343052
-----------------
923290 产生的回滚段信息
SQL> insert /*+ append */ into t select * from dba_objects; direct insert
13197 rows created.
SQL> commit;
Commit complete.
SQL> select usn,RSSIZE ,WRITES from v$rollstat;
USN RSSIZE WRITES
---------- ---------- ----------
0 385024 7620
1 253952 11174528
2 2220032 12266768
3 2220032 9678420
4 2220032 9817356
5 122880 92562
6 122880 0
7 1171456 234
8 122880 0
9 122880 0
10 122880 0
11 rows selected.
SQL>
SQL> select 11174528 - 11173844 from dual;
11174528-11173844
-----------------
684
SQL> select 92562 - 90478 from dual;
92562-90478
-----------
2084
SQL>
在这里我们核对任意一个回滚段的生成量,发现几乎很少
由此我们几乎可以下个结论,不管表是否在nologging 下,只要是 direct insert,就不会对数据内容生成undo,也就是不会为insert而记录 rowid
接下来我们进一步实验,在表同样处于 logging 状态下测试
SQL> select * from v$sysstat where name = 'redo size';
STATISTIC# NAME CLASS VALUE STAT_ID
---------- -------------------- ---------- ---------- ----------
133 redo size 2 133173584 1236385760
SQL> insert into t select * from dba_objects;
13197 rows created.
SQL> select * from v$sysstat where name = 'redo size';
STATISTIC# NAME CLASS VALUE STAT_ID
---------- -------------------- ---------- ---------- ----------
133 redo size 2 137974492 1236385760
SQL> select 137974492 - 133173584 from dual;
137974492-133173584
-------------------
4800908 正常插入产生的日志
SQL> roll;
Rollback complete.
SQL> select * from v$sysstat where name = 'redo size';
STATISTIC# NAME CLASS VALUE STAT_ID
---------- -------------------- ---------- ---------- ----------
133 redo size 2 140087680 1236385760
SQL> select 140087680 - 137974492 from dual;
140087680-137974492
-------------------
2113188 正常插入后回滚所产生的日志
SQL> insert /*+ append */ into t select * from dba_objects;
13197 rows created.
SQL> select * from v$sysstat where name = 'redo size';
STATISTIC# NAME CLASS VALUE STAT_ID
---------- -------------------- ---------- ---------- ----------
133 redo size 2 141531644 1236385760
SQL> select 141531644 - 140087680 from dual;
141531644-140087680
-------------------
1443964 direct 插入产生的日志
SQL> roll;
Rollback complete.
SQL> select * from v$sysstat where name = 'redo size';
STATISTIC# NAME CLASS VALUE STAT_ID
---------- -------------------- ---------- ---------- ----------
133 redo size 2 141534344 1236385760
SQL> select 141534344 - 141531644 from dual;
141534344-141531644
-------------------
2700 direct插入后回滚产生的日志
SQL>
从这里的实验可以看出,在 direct insert 后回滚数据,实际上并没有进行数据的 删除操作
而是仅仅对空间进行了回收。若是删除,不可能只产生这么少的 redo,这里从另一个侧面证明
即使 logging 下的 direct insert 对于回滚信息,也是不会对数据产生 undo 而仅仅产生空间变化的 undo