我的oracle笔记-02 之 回滚段

来源:互联网 发布:手机淘宝无响应怎么办 编辑:程序博客网 时间:2024/05/19 15:20

看来是起点的文章看多了,居然学人家开始玩连载了。

   首先要说明的是:我不是什么ORACLEDBA,事实上我基本上没怎么用过ORACLE,所以如果要解决ORACLE中诸如怎么安装RAC之类的问题,我并不会比其它人做得更好。更多的时候,我只是以“换成是我,应该怎么做”的角度,去试图理解ORACLE们的设计理念,并偶尔会进行些验证。所以我不敢保证我所写的与ORACLE的实现完全一致,如有错误,敬请指出并原谅。

   看了上一篇文章中大家的评论,我想再次强调:ORACLE是行级并发,也就是说,两个并发事务可以同时修改同一数据块中的不同行,事实上我不知道现在还有哪个商用数据库会是页面级并发。上篇文章重点是介绍协议,其中所说的数据实际上指的是行。但我们经常说ORACLE是页面级MVCC,指得是其构造历史版本的单位,好吧,这些问题以后会说明的,下面我们继续。

   我在基本协议中说“当你更新时,你会产生一个新的版本”,好吧,你不会真的相信ORACLE会这么干对吧,ORACLE不是PG,它不会在一个工业系统中引入这样的设计。所以我们需要先回忆数据库教科书中关于日志的描述,日志分为REDOUNDO两部分,也即是所谓的后项和前项,其中REDO用于重复历史(持久性),UNDO用于回滚,很明显,UNDO可以用来构造历史版本,如果我们把发生在某数据的所有更新照时间序从当前版本倒退回去,我们就可以得到该数据在任何时间点上的历史。

   所以ORACLE总是在数据空间中只保存数据的最新版本,而把所有的UNDO信息存放在专门的结构——回滚段中,回滚段不仅用于事务的回滚,也用于构造版本。

   ORACLE总是努力保持着回滚段的规模,或者说,它总是积极地回收回滚段的空间,避免其过大,请允许我这么说,所以如果一个事务持续的时间非常长,你可能无法构造出你能看到的版本,因为你的SnapshotSCN太早了,使得回滚段中构造版本所需的UNDO记录早已经被回收并重用了,这时你就会碰到著名的错误——“Snapshot too old”。

   无数DBA为此问题头疼不已,尽管AUM的出现让这一问题大大缓解了,但有时我们仍然会问,为什么回滚段不能无限大呢,存储不是很便宜吗,为什么不能象其它数据库那样,把UNDOREDO都放在日志中,然后直接通过日志来构造版本呢?

   这个问题可以从两方面来看,首先,无论你的回滚段怎么组织,不同的人会对不同的数据构造版本,他们会同时访问回滚段中不同的部分,所以在ORACLE中,用户对回滚段的访问是高离散的,如果回滚段过大,会造成严重的IOPS性能问题。另一方面,绝大部分的事务都非常短,它们实际上并不关心回滚段的大小,但总有些人不守规矩,比如你敲了个begin,然后突然内急了,我不清楚ORACLE是否真的能区分这种行为和一个确实需要长时间运行的统计查询的区别,但如果真的因为少数人而导致回滚段过度增长从而降低系统性能,我们应该考虑牺牲掉这颗老鼠屎来挽救整锅粥。

   ORACLE的痛苦在于:它需要仔细地设计回滚段的代码,在保证回滚段合理大小的同时,尽可能降低“Snapshot too old”出现的概率。

   所以ORACLE会用一独立的回滚段结构来管理所有UNDO信息。回滚段是按照事务聚集的,也就是说同一事务的所有UNDO纪录按照顺序连续存放在一个或多个undo block中。这样做有很多好处,首先是回滚变快了,更重要的是,同日志那种按照产生顺序连续存放的组织方式相比,这种方式更加利于空间的回收,因为不会出现整个空间中大部分日志都可以回收,却因为有一个较早开始的未提交的更新还活着而导致日志撑爆的现象(看看SQL SERVER),同时,这种方式也不易产生竞争热点。

   因此,一个重要的结论是:在ORACLE中,回滚段是稀缺资源,这个结论在后面还会被反复提到。所以我们看到ORACLE不会去采用REDO/UNDO存放在一起的结构;我们会看到在Flashback中,系统会将UNDO信息拷贝到单独的Flashback日志中,而不是让其在回滚段中停留足够长的时间。

最后说说REDO,前面说,在我们更新数据之前,我们把REDO产生到日志中,把UNDO产生到回滚段中,好吧,这个只完成了一半,在日志看来,数据和回滚段并没有任何区别,所以当我们把UNDO加入回滚段时,我们实际上是在进行一次对回滚段的更新,所以我们要为这个更新产生REDO并加入到日志中。所以在ORACLE中,日志实际上是数据和回滚段的REDO,它被叫做REDO LOG,因为它确实是redo-only的。

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

 

0 0