oracle动态链表,关于事务表的理解 - Oracle专题深入讨论 - ITPUB论坛-中国专业的IT技术社区...

本帖最后由 13811135929 于 2016-1-13 16:19 编辑

结合《oracle核心技术》(JL)、网上的资料以及自己的理解,对于事务表在测试环境中做了如下实验,如有错误,还请大师指点数据库版本信息如下:

SCOTT>select * from v$version;

BANNER

------------------------------------------------------------------------------------------------------------------------------------------------------

Oracle Database 10g Enterprise Edition Release 10.2.0.1.0 - Prod

PL/SQL Release 10.2.0.1.0 - Production

CORE    10.2.0.1.0      Production

TNS for Linux: Version 10.2.0.1.0 - Production

NLSRTL Version 10.2.0.1.0 - Production

oracle开始事务前,根据现有undo段的情况选择一个undo段,此处假设选择了_SYSSMU5$

事务表控制部分:

session2:alter system dump undo header '_SYSSMU5$';

file:///C:/Users/icbc/AppData/Local/Temp/enhtmlclip/Image(9).png

dd06a1abc3fb84da465ff4eff32374f6.gif

1.PNG (70.93 KB, 下载次数: 13)

2016-1-12 15:31 上传

file:///C:/Users/icbc/AppData/Local/Temp/enhtmlclip/Image(11).png

一般情况每个undo段头会有0x2f个事务表槽(oracle版本不同,事务表槽的个数可能不同),一个事务会占用其中一个事务表槽,undo段头事务表会自动维护一张链表,oracle根据链表的顺序对事务表进行重用。

注意上图中chd以及ctl两个部分,其中chd指向了下一个将被使用的事务槽,ctl为事务槽链表的最后一个节点;而0x0015的事务槽uel字段指向了链表的下一个节点(0x0018).因此现在链表的情况如下:

0x0015->0x0018->0x0006->.......->0x000d

session1:update t set OBJECT_NAME='a' where OBJECT_ID=2;

session2:alter system dump undo header '_SYSSMU5$';

file:///C:/Users/icbc/AppData/Local/Temp/enhtmlclip/Image(4).png

file:///C:/Users/icbc/AppData/Local/Temp/enhtmlclip/Image(5).png

dd06a1abc3fb84da465ff4eff32374f6.gif

2.PNG (70.98 KB, 下载次数: 4)

2016-1-12 15:31 上传

file:///C:/Users/icbc/AppData/Local/Temp/enhtmlclip/Image(6).png

发起新事务后,再次转存_SYSSMU5$段头后,观察事务槽的情况发现新事务确实占用了0x0015,同时chd变为了0x0018,因此现在链表的情况如下:

0x0018->0x0006->.....->0x000d

session1:commit;

session2:alter system dump undo header '_SYSSMU5$';

file:///C:/Users/icbc/AppData/Local/Temp/enhtmlclip/Image(7).png

dd06a1abc3fb84da465ff4eff32374f6.gif

3.PNG (55.04 KB, 下载次数: 5)

2016-1-12 15:32 上传

file:///C:/Users/icbc/AppData/Local/Temp/enhtmlclip/Image(8).png

当事务提交后,再次转存_SYSSMU5$段头后,发现ctl更换为了刚刚被占用的事务槽0x0015,因此现在链表的情况如下:

0x0018->0x0006->.....->0x000d->0x0015

通过以上的内容可以非常清晰的看出了chd以及ctl的作用:即chd(chain head)和ctl(chain tail)分别为事务表链表的头和尾,每个事务表槽又通过uel字段指向了链表的下一个,从而形成了一个有序的链表。有了此链表,可以让新事务尽快的找到对应的事务表槽并进行占用。

以下再对TRN CTL其他字段进行分析

session2:alter system dump undo header '_SYSSMU5$';

file:///C:/Users/icbc/AppData/Local/Temp/enhtmlclip/Image(14).png

dd06a1abc3fb84da465ff4eff32374f6.gif

4.PNG (54.79 KB, 下载次数: 3)

2016-1-12 15:33 上传

file:///C:/Users/icbc/AppData/Local/Temp/enhtmlclip/Image(18).png

session1:select dbms_flashback.get_system_change_number from dual;

输出结果:734647

update t set OBJECT_NAME='b' where OBJECT_ID=2;

session2:alter system dump undo header '_SYSSMU5$';

dd06a1abc3fb84da465ff4eff32374f6.gif

5.PNG (51.76 KB, 下载次数: 9)

2016-1-12 15:34 上传

file:///C:/Users/icbc/AppData/Local/Temp/enhtmlclip/Image(15).png

file:///C:/Users/icbc/AppData/Local/Temp/enhtmlclip/Image(19).png

请注意TRN CTL的uba和scn字段:

uba:0x00800068.0179.03->0x00800068.0179.04

scn:0x0000.000b1b69->0x0000.000b1b73

0x0000.000b1b73:此scn为事务表槽被占用之前的scn,即上次用此事务表槽的事务的提交scn.还有一点该scn为_SYSSMU5$段中所有事务表中已知的最小的scn.

0x00800068.0179.04 此uba的地址代表什么?让我们来查询v$transaction视图进行确认

file:///C:/Users/icbc/AppData/Local/Temp/enhtmlclip/Image(20).png

dd06a1abc3fb84da465ff4eff32374f6.gif

6.PNG (65.61 KB, 下载次数: 3)

2016-1-12 15:35 上传

从v$transaction的输出可初步判断:0x00800068.0179.04应该为新事务undo的第一个记录.那么确认这个猜想呢?也许你会说我们的dml语句只占用了一个undo记录,你凭什么判断该记录就是事务的第一个undo记录呢?

session1:update t set OBJECT_NAME='b'

执行了上述语句后,再去查看v$transaction,通过USED_UBLK字段可以判断事务使用了1021个undo block,且第一个undo block为104(START_UBABLK), 最后的block为1697(UBABLK).

dd06a1abc3fb84da465ff4eff32374f6.gif

7.PNG (66.18 KB, 下载次数: 5)

2016-1-12 15:36 上传

file:///C:/Users/icbc/AppData/Local/Temp/enhtmlclip/Image(21).png

那我们再次转存_SYSSMU5$信息

session2:alter system dump undo header '_SYSSMU5$';

file:///C:/Users/icbc/AppData/Local/Temp/enhtmlclip/Image(16).png

dd06a1abc3fb84da465ff4eff32374f6.gif

8.PNG (53.1 KB, 下载次数: 3)

2016-1-12 15:37 上传

file:///C:/Users/icbc/AppData/Local/Temp/enhtmlclip/Image(17).png

虽然事务又占用了大量的undo block,细心的你可能发现TRN CTL部分并没有发生任何变化,因此可以进一步断定uba的确为新事务的第一个undo记录.你可能还会发现事务表槽对应的dba由0x00800068变成了0x008006a1.对0x0080061计算后发现,其地址为datafile=2 block=1697,发现了什么?对,事务表槽对应的dba记录的是当前事务占用的最后一个undo block地址。

上面对整个事务控制部分主要字段进行了详细的介绍,下面我们再深入的研究一下undo block的内容

对0x00800068.0179.04进行转存

session2:alter system dump datafile 2 block 104;

file:///C:/Users/icbc/AppData/Local/Temp/enhtmlclip/Image(22).png

dd06a1abc3fb84da465ff4eff32374f6.gif

9.PNG (169.26 KB, 下载次数: 6)

2016-1-12 15:39 上传

可以看到uba为上一个被占用的事务表槽的第一个undo记录(注意,这个uba肯定不是slt:0x10,而是别的slot),而prv tx scn为覆盖slt:0x10之前事务表槽的提交scn,prev brb为覆盖slt:0x10之前事务表槽的事务的最后一个undo块,txn start scn:scn为覆盖slt:0x10之前事务的开始scn.

ok,让我们来再次屡屡事务表的机制,假设新建数据库,事务表未使用过。

1.第一个事务A用了slot:0x0010,A开始后TRN CTL的uba记录了A的第一个undo记录dba-A,同时也记录了slot:0x0010之前的状态 (包括提交scn,undo的最后一个块)。

2.隔了一段时间,该段的第二个事务B使用了该段,根据chd的标记占用了slot:0x000a,B开始后TRN CTL的uba更改为B的第一个undo记录dba-B,另外dba-B中记录了dba-A的地址和slot:0x000a之前的状态(包括提交scn,undo的最后一个块)

那么问题来了?怎么回退事务表呢?

1.oracle找到TRN CTL的uba dba-B(从上面的描述可以知道此为最新事务的第一个undo记录),从该uba的第一行可以得知最新事务占用的slot:0x00a,且原来占用slot的主要信息也进行了记录:wrap#-1,uel更改为现在TRN CTL的chd,scn更改为prv tx scn,dba更改为prev brb.

2.如果回退一步不满足要求,那么则再进行回退,即回退dba-B中记录的上一个TRN CTL的uba地址dba-a,从该uba的第一行也可得知次新事务占用的slot:0x0010,且原来占用slot的主要信息也进行了记录:wrap#-1,uel更改为0x000a,scn更改为prv tx scn,dba更改为prev brb.

.........

经过上述的描述,可以简单的概括为:通过事务的第一个undo记录链表完成了事务表的回退,为块延迟清除找到准确的提交scn提供了强有力的保证。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值