还记得以前部门同事一起讨论过一个问题, 能否让oracle 9i ,10g standby数据库 可以边恢复边提供读服务? 提供像11g active standby 类似的功能,还问过oracle 是否有专门的包可以下放到9i,10g 数据库,打个补丁之类的就可以提供此功能
最近发现市场上竟然真的有这样的产品,据说卖的很不错,主要应用在移动电信领域,了解了一下,基本知道其中的做法,里面的有些想法还是蛮有意思的,跟大家分享一下:
其实原理也很简单,他们是解析了oracle redolog 文件,不过他们解析的是变化的块号,然后根据变化的块号,到主库去将文件中的数据块读取出来,最后覆盖到standby 中对应的数据文件(standby 一直是处于open read only 状态)。
这样覆盖后,就有个需要处理的地方
1 . 如果原先有一个数据块被cache ,那么覆盖了数据文件后,为了得到最新的数据,就需要程序定期去刷新buffer cache ,从而才能让oracle 去读取最新的数据块。
2. 由于程序去定期刷新buffer cache ,那么如果发出一个select 查询,就会出现有些块在内存中数据已经是比较老的,有些数据块直接从文件中读取读取的是最新的数据块,这样就会造成数据不一致的情况。 那这种情况怎么去处理呢 ? 是否记得oracle 中有个语法 select * from table as scn of XX ? 让oracle 自己去查询某个时间点的数据,自己去构造一致性读取。但是这样就会造成另外一个问题,这个SCN 号如何去取呢 ? 那么很简单,我们只要select min(scn) from x$bh where scn > 我上次flush buffer cache 时间点的SCN, 得到buffer cache 中最小数据块的SCN 号,然后发出一个命令,以小于buffer cache 中最小SCN 号的方式去查询,那么就可以查到一致的数据。比如buffer cache 中数据块最小的SCN 号 是100 ,那么我们select * from table as scn of 95 ,那么肯定数据查出来在那个时间点是一致的。 这样就带来另外一个问题,是不是需要让应用去改造sql 呢,每个select 都要加上scn 号去查询? 这边就用了一个技巧,先得到全局SCN 号在SGA 中的内存地址,然后用程序去修改成我们需要的SCN 号,这样oracle 去查询的时候总是会去构造一致性查询
好了,解决了上面的问题,还有一个问题就是DDL 引起的share pool 的变化,这就需要程序去定期刷新shared pool ,虽然我一直认为这会存在问题,但是据卖这款产品说,客户反映用的还蛮好
看的出来,上面做的东西在OLTP 中不太好用,跟oracle 11g 的active standby 也存在差距。但是如果用在报表系统或者给DW 批量拉数据,还是非常不错的。在保证有备份的同时,又能给用户提供服务,最大化利用了资产