我的oracle笔记-03 之 ITL

我们已经了解了ORACLE MVCC的基本协议,并且知道了用于构造历史版本的UNDO信息被集中存放于回滚段中。在事务处理中,你读到的版本实际上是你能读到的所有数据版本中最新的那个(这点不同于Flashback),这个版本在ORACLE中被称为CR版本(Consistent Read)。从实现的角度来说,如果把对数据的所有更新反向连接起来并遍历,那么第一个CommitSCN<=你的SnapshotSCN的版本就是你的CR版本。

   CR版本的构造是MVCC的核心,但是说真话,我到目前为止,仍然不能确认自己是否真的理解了ORACLE实现页面级CRblockCR)的设计初衷何在,所以为了论述更加简单,让我们首先来看看,如何构造行级CR。简单地说,假设我们需要在每行的开头维护一个header,那么需要在这个header中加入哪些信息,才可以保证行级CR的实现。

   为此,让我们重新回到MVCC基本协议,当我需要更新或读取数据时,我需要首先确认该数据当前是否已经被我更新,如果是,那么我可以直接操作这个数据,为此,我们必须把事务标识(Xid)加入到Header中。如果不是,那么我需要维护一条UNDO的反向链表,并沿着这条链接依次undo各版本,为此,我可以把对数据最近一次更新的UNDO信息在回滚段里的地址(Uba)也加入到header,这相当于记录了那条链表的头指针,当数据被更新时,我们需要同步修改header,并为数据和header一起生成UNDOREDO(注意这点),这样,当我们UNDO一条记录时,数据头header中的Uba会被自动更新成上一次更新的UNDO地址,这相当于实现了反向链表遍历的功能(非常实用的设计)。最后,在我们沿着Uba反向UNDO时,我们需要依次检查各版本的CommitSCN,当它<=我的SnapshotSCN时,CR构造完成,为此我需要把CommitSCNScn)也记录到header中。

   至此,我们知道header中应该包含,我们也可以隐藏Scn,而将它记录在事务表中,并以Xid进行索引,但这样做有两点问题,你如何保证Xid在事务表中不被重用,更重要的是,你的90%路径是什么?应该是大多数行对你是可见的,你不需要构造CR,所以从性能上考虑,我们需要这个判断在行内完成。

   ORACLE中,出于扩展性的考虑,XidUba的长度为8个字节,而Scn6个字节,考虑到空间对齐的需要,我们还可以多存放两个字节的其它信息,比如事务状态(Flag),当前事务是活跃还是提交?维护这样的状态有利于简化代码;再比如行锁(Lck),注意ORACLE MVCC中是没有读锁的,将行锁直接持久化在行上是一个不错的设计,因为更新已经必然发生,而它避免了维护单独的内存结构并通过HASH表去访问,同时也不必考虑锁升级(Lock Escalation)。

   接下来的问题是,也许ORACLE无法接受这样的设计,它觉得空间实在太浪费了,另一种可能是,ORACLE的页面级CRORACLERAC中页面级操作同步是一个一体的设计。我无法考证这点,我只能说,如果是出于后者的考虑,那么正如我在前面的文章中提到的:“如果ORACLE MVCC的发明者一开始就想到了RAC会获得成功,那就实在太令人崇拜了”。

   无论是什么原因,最终的结果是ORACLE放弃了行级CR,所以我们需要合并同类项,我们需要把同一事务在页面上的所有更新用一个header表示,在ORACLE中,这个结构被叫做ITL,它位于页面的头部(row directory之前),ITL不再是行相关的,它是事务相关的。ITL的引入,使得不管一个事务在同一页面上改了多少次,都只会产生一个header,很明显,这样节省了空间,数据上只保留了指向ITL的下标和Lck信息,而ITL中则记录了锁的个数(Lcks)。

   直到目前为止,一切看上去都还正常,但是问题很快来了:如果你现在想构造一行的CR,你突然发现做不了了,你必须一次UNDO掉该事务在行所在页面上的所有更新,如果你构造的CR版本存在时间较早,那么你需要进行大量的UNDO动作,而其中大部分的动作可能都是无用功。在这种情况下,你似乎别无选择,你只能选择按整个页面来构造CR,一次回滚掉所有在你的SnapshotSCN之后发生的ITL

   我们很容易找到这种方案的弱点,假设页面上有大量的更新,而每个事务又需要构造该页面的CR版本,这对于回滚段来说真是一场灾难。

   好吧,我只能说,如果ORACLE当初实现页面级CR的原因真的仅仅只是为了节省空间,那我很难说这种方案是好的,特别是面向高负载的OLTP类应用,基于现在的硬件条件,高离散的并发访问,行的长度有那么重要吗?你可以说OLTP事务都很短,它们通常只会在特定的页面上修改一行,如果这样的话,合并同类项的意义又在哪呢?在行级CR中,那些header同样也可以动态生成。

所以最终的结果是:当我们再次说“在ORACLE中,回滚段是稀缺资源”这句话时,我们必须把“稀缺”这两个字重复10次,不,是100次。所以我们同样会理解,对于每个ORACLEDBA来说,把更新热点分散到不同的页面中,是一项多么重要的工作。

转载自:http://blog.sina.com.cn/s/blog_d3bf72ff0101nuui.html

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值