1.什么时机产生UNDO和REDO
有DML就会产生UNDO,有UNDO就会产生此UNDO对应REDO
执行DML,再执行COMMIT是把位于内存的日志缓存区数据转储到磁盘的在线重做日志组
执行了COMMIT,不一定会修改磁盘数据,磁盘数据的DBWn进程触发机制不依赖COMMIT.
UNDO是回滚段,磁盘上
测量REDO是测量REDO LOG FILE 还是 REDO BUFFER ?虽然他们结果应该是相等的
2.什么样的操作不会产生UNDO和REDO?
UNDO用于事务回滚,所以DML语句一般都会产生UNDO(直接路径加载+nologging不会产生或者产生很少的UNDO和REDO)
REDO用于事务恢复,临时表上的数据用完即丢,所以临时表上的DML不产生REDO,但是临时表发生DML的时候会产生UNDO(因为临时表上也可以执行rollback,有回滚就肯定有UNDO),这部分UNDO会产生REDO
3.临时表最好只进行INSERT 和SELECT
原因:
虽然临时表本身的操作不会产生REDO,会产生UNDO以及这部分UNDO的REDO,所以如何减小UNDO,DELETE产生的UNDO最多,而UPDATE对索引影响比较大,因此如果临时表上有索引,此部分索引的修改也会产生UNDO,也会针对这部分UNDO产生REDO
4.如何最小化临时表的REDO产生
ALTER SYSTEM/SESSION SET TEMP_UNDO_ENABLED =TRUE
前面我们知道临时表的操作,UNDO产生不能避免,不过还是会产生一点点REDO,能不把这一点点REDO也去掉。
我们知道临时表的操作是发生在临时表表空间,临时表空间的DML操作不会产生REDO。是临时表空间的UNDO会产生REDO,原因是UNDO是放在UNDO表空间,如果我们把临时表对应的UNDO也放在临时表空间,而不是UNDO表空间,那么这一点点REDO也不会产生了
5.测量开启 TEMP_UNDO_ENABLED前后的REDO,UNDO变化
结论:临时表写入1M数据。开启TEMP_UNDO_ENABLED之后,事务产生的REDO从140K降低为0.1KB
--为了方便换算,写1m的数据进行测试
create global TEMPORARY TABLE tem_test(a varchar2(1024)) on commit preserve rows ;
--创建普通表
create TABLE tem_test_normal(a varchar2(1024)) ;
--简单起见只测量insert,DML中insert最多的REDO,最少的UNDO,UNDO数量级应该和存储ROWID需要的字节量一致
--使用跟踪打印出来的redo更准确
--======================================================================= --新开窗口1--START begin for i in 1..1024 loop insert into tem_test(a)values(rpad('X',1024,'X')); end loop; end; --redo 632->151716 :0.14m redo SELECT a.name ,b.value FROM v$statname a ,v$sesstat b WHERE a.statistic# = b.statistic# AND A.NAME = 'redo size' AND B.SID=USERENV('SID') --事务产生的undo 0-73728:0.07m UNDO SELECT t.used_ublk*8*1024 FROM v$session s ,v$transaction t WHERE s.saddr = t.ses_addr AND s.sid = userenv('SID'); --新开窗口1---END --======================================================================= --新开窗口2---START ALTER SESSION SET TEMP_UNDO_ENABLED =TRUE; begin for i in 1..1024 loop insert into tem_test(a)values(rpad('X',1024,'X')); end loop; end; --redo 676->948 : 很少 SELECT a.name ,b.value FROM v$statname a ,v$sesstat b WHERE a.statistic# = b.statistic# AND A.NAME = 'redo size' AND B.SID=USERENV('SID') --事务产生的undo 0-8192:8KB UNDO SELECT t.used_ublk*8*1024 FROM v$session s ,v$transaction t WHERE s.saddr = t.ses_addr AND s.sid = userenv('SID'); --查询 select * from v$tempundostat --新开窗口2---END --======================================================================= --新开窗口3---START begin for i in 1..1024 loop insert into tem_test_normal(a)values(rpad('X',1024,'X')); end loop; end; --redo 676->1435724 :1.36m redo SELECT a.name ,b.value FROM v$statname a ,v$sesstat b WHERE a.statistic# = b.statistic# AND A.NAME = 'redo size' AND B.SID=USERENV('SID') --事务产生的undo 0-81920: 80k UNDO SELECT t.used_ublk*8*1024 FROM v$session s ,v$transaction t WHERE s.saddr = t.ses_addr AND s.sid = userenv('SID'); --新开窗口1---END select sum(lengthb(rowid))/1024||'KB' from tem_test_normal;--应该是10K-100K左右 --=======================================================================
点击加载更多