《Oracle内核技术揭秘》(笔记)--第六章 UNDO 回滚段

本章没有讲回滚段如何在事务中使用,重点是回滚段的管理。

 

1.事务基本信息

回滚段,和表段、索引段一样,就是一个“段”空间。用来保存前映像相关数据。不同之处是:由Oracle自行管理。Oracle会在需要时创建回滚段,不需要时删除,空间不够时自动扩展。

 

回滚段分为在用(online,当前回滚段)不在用(offline,非当前回滚段)

查看所有回滚段:dba_rollback_segs视图

只查看当前回滚段:

select * from v$rollname;

 

0 SYSTM回滚段:自用,为数据字典的相关事务提供服务

余下的:自动创建。这10个都是普通的段,与表、索引段没有区别

 

所有针对段的普通视图,都可以查看UNDO段的信息。如:dba_segments、dba_extents、dba_undo_extents(比dba_extents多一个STATUS,记录是否有活动或未过期的事务)等

可以从dba_setments查看UNDO段的具体信息

 

select header_file, header_block,blocks, segment_type
from dba_segments 
where segment_name = 'XXXX上面查出来的某个名字'

很清晰的显示:

段头在3号文件128号块, 共2704块,类型是UNDO。

在dba_extents中,还能查到它的具体区的信息:

 

select extent_id, file_id, block_id, blocks from dba_extents
where segment_name='上面查出来的段名字';

把这个段2704个块的分布,都列出来了。

 

9个区,前面的8个块(64KB),后面大的8MB。UNDO的区大小不能设置为统一,是自动管理的

 

至于自动创建几个(是不是10个)UNOD段,是不一定的,取决于UNDO表空间大小。

创建UNDO表空间语句:

create undo tablespace myundo DATAFILE '+dg/myundo.dbf' size 512K;

 

随着事务增加,Oracle会逐渐创建越来越多的UNDO段。倾向于每一个事务都独占一个回滚段直到认为UNDO表空间剩余空间不多时(所谓不多,就是UNDO表空间剩余空间滑落到50%左右时为止),才会让新、旧事务共享一个回滚段。Oracle回滚段策略是:创建更多、更小的回滚段,而不是创建少量巨大的回滚段。

 

例子中,通过创建多个事务,观察上述视图查看回滚段变化。

也可查看事务被分配到哪个回滚段:

select xidusn, UBAFIL, UBABLK, UBAREC from v$transaction;

XIDUSN:回滚段编号,随着事务增多,在原来基础上,增加了个18号回滚段。

 

如果并发事务减少,不再需要很多回滚段,会将一些回滚段的状态改为OFFLINE。在别的回滚段需要空间时,OFFLINE的回顾段可以被删除,腾出空间

 

 

2.回滚段重用规则

 

回滚段重用:只要事务提交或过期了,它的前映像所占的回滚块,就可以被其他事务覆盖

但重用有一定规则。

SEQ值:回滚块的块头有一个SEQ值。看图说话

1号区前3个块SEQ为7。当有事务占用1号区第4块时,它的SEQ也会变为7,占用第5块,也变为7。

继续往前,占用第二个区第1块时,这个区的SEQ变为8。2号继续占用,持续用8,等到切到3号区时,SEQ都为9。就这样循环。

 

规则1:被重用块的SEQ值必须小于区新一轮的SEQ值。并不是已提交时间超过undo_retention的UNDO块都可以被覆盖。

A事务占用0号区3号块,SEQ时10。新来事务B从4号块开始,且马上提交。但A没提交,继续做事务,3号不够了,需要再占用一个回滚块。此时B已经提交,且已经超过undo_retention时间,A会覆盖B的块吗?不会,因为4号块的SEQ是10,A需要跳过这个块用后面的。

补充:Undo_retention是一个“目标期望值”。用户设置出这个值之后,Oracle内部会尽量保证将Undo数据保留超过undo_retention设置的时间。在这个过程中,Oracle会涉及到比如尝试拓展Undo表空间数据文件、Undo Segment管理等内容。但是,如果“现实比较残酷”,比如说Undo使用紧张、没有额外的方法,那么这个时间段也是不能保证的。

 

规则2:不能跳过包含未提交事务的块重用后面的块需要进行UNDO段膨胀

 

2号区3号块有未提交事务;其他事务一直往后推进,使用跟后面的块。当循环回到2号区时,2号区有未提交事务,则:2号区任何一个块都不能被重用,且不能跳过2号区使用3号区的块

2号区不能用了,膨胀。如果新3号区一直不能用,继续膨胀。

规则3:如果因不提交事务阻止使用后面(不能是前面的)的区,其他回滚段在需要申请空间时,可以把后面的区偷走

3号区3块不提交,4号区不能用,被其他回滚段偷走,这个段剩下3个区。

 

因此:很多小事务不提交,会造成活动事务虽然不占太多UNDO空间,但会报UNDO空间无法扩展,因为被阻塞住了。

 

查找持续时间太长的事务:

v$transaction的START_TIME记录事务开始时间。将ADD列和v$session的TADDR关联,能得到长时间不提交事务的SID,还有SQL_ID。通过后者可以在v$SQL中找到SQL_TEXT。

v$undostat中

EXPSTEALCNT记录了偷窃过期区的次数:偷窃次数过多,说明UNDO段在急剧膨胀,UNDO空间不足。

EXPBLKRELCNT记录偷窃成功次数

UNXPSTEALCNT记录偷窃未过期区次数(老东西了,因为有und0_retention,10g后就不允许偷窃未过期的了,所以为0)

UNXPBLKRELCNT记录成功偷窃未过期的块数(同上,老东西)

 

在AWR中,UNDO信息,最后一列,uS:UNXPSTEALCNT、uR:UNXPBLKRELCNT、eS:EXPSTEALCNT、eR:EXPBLKRELCNT、uU:UNXPBLKREUCNT、eU:EXPBLKREUCNT

 

 

回滚段重用机制总结

1、选择目标回滚段

事务开始时,根据进程PID号计算一个随机数,然后根据随机数从多个回滚段选一个回滚段,作为目标回滚段。

或者Server进程已经选了一个回滚段,事务前映像占满一个UNDO块,Server要在同一个回滚段再找一个UNDO块,继续记录前映像。

2、三种情况

1)确定目标回滚段SEQ值最大区,在此区寻找第一个SEQ值低于其他块的UNDO块;

2)如果这个区里面所有SEQ一样,选下一个区。这就是一次Wrap(v$rollstat中的WRAPS+1,代表要开始用下一个区

3)如果下一个区因为有未提交事务,需要区膨胀。v$rollstat的EXTENS列会+1,表示出现一次膨胀。

如果UNDO表空间中有Free区,则选择它作为膨胀区(加入为提交事务所在区之前)

如果没有Free的,开始偷窃

3、偷窃:从跟其他回滚段偷窃过期的区,偷窃以区为单位。

4、偷窃不成功,扩展UNDO表空间。如果扩展失败,而UNDO表空间默认设置为RETENTION GUARANTEE,不能重用未过期块,则只能:报ORA-30036:UNDO表空间无法扩展之类空间错误。

如果UNDO表空间被设置为RETENTION NOGUARANTEE,此时还可以不报错,继续尝试用未过期区。

5、首先常用本段未过期区。如果还没有,从其他段偷窃未过期区。

6、还偷不到,只能报30036错误了。

 

一路各种尝试。

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值