陈老师:1415968548 郑老师:2735197625 乐老师:354331153
客服热线:
19941464235/19906632509(微信同号)

客服微信

云贝教育 | 【技术文章】temp redo undo 测试

作者:刘晓峰
http://www.tdpub.cn/Home/Blog/detail/action/preview/id/1294.html
发布时间:2022-10-25 17:32
浏览量:487

作者:刘晓峰

原文链接:TDPUB数加社区



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左右

--=======================================================================