11G standby提供了real time query的功能,通过这个功能,我们可以结合lgwr+async来做到实时standby查询,
给我们做读写分离提供了遐想空间,最近和老郑测试了下这个功能的实时性,希望对大家有所帮助
测试环境:
redhat linux as 4.7(64bit)
11.1.0.7.0 lgwr + async 20480 + real time query
主库:10组512M的联机日志
备库:11组512M的standby logfile
测试方法:
循环插入记录,为了增大日志量,起了6个进程,插入test1-test6
declare v_counter pls_integer := 0;
begin
for i in 1..100000000 loop
insert into $1 (id,mdate,mm) values(i,sysdate,’wo shi ni ba’);
v_counter := v_counter + 1;
if v_counter = 10 then
commit;
v_counter := 0;
end if;
end loop;
end;
/
以表test1为参考,每隔1秒查询主库和备库的最大ID,还有插入的时间,如果是完全实时,这两个数值应该相等,
通过两边的max(id)和maxid对应的时间,可以看出real time query的延迟,采样结果保存于rquery_time表
测试的日志量大家可以自己加压设置,本次测试日志量是37M/S,让我有点吃惊,但多次statspack统计的结果和日志切换的频率计算,
就是如此
Load Profile Per Second Per Transaction Per Exec Per Call
~~~~~~~~~~~~ —————— —————– ———– ———–
DB time(s): 3.1 0.0 0.00 6.78
DB CPU(s): 3.0 0.0 0.00 6.65
Redo size: 37,575,874.7 5,286.1
Logical reads: 312,674.9 44.0
Block changes: 303,749.8 42.7
Physical reads: 8.4 0.0
Physical writes: 2,256.8 0.3
User calls: 0.5 0.0
Parses: 4.1 0.0
Hard parses: 0.5 0.0
W/A MB processed: 0.0 0.0
Logons: 0.0 0.0
Executes: 71,089.5 10.0
Rollbacks: 0.0 0.0
Transactions: 7,108.4
declare v_max_stb pls_integer := 0;
v_max_pri pls_integer := 0;
v_date_stb date;
v_date_pri date;
begin
for x in 1..1000000 loop
–获取主库最大ID,最大时间
select max(id) into v_max_pri from test1;
select mdate into v_date_pri from test1 where id = v_max_pri;
–获取备库最大ID,最大时间
select max(id) into v_max_stb from test1@ctrdmsb;
select mdate into v_date_stb from test1@ctrdmsb where id = v_max_stb;
–保存结果
insert into rquery_time
(primary_max_id,standby_max_id,primary_time,standby_time)
values
(v_max_pri,v_max_stb,v_date_pri,v_date_stb);
commit;
–get sleep
dbms_lock.sleep(1);
end loop;
end;
/
–查询结果
select PRIMARY_MAX_ID - STANDBY_MAX_ID as max_deff,(PRIMARY_Time - standby_Time) * 24 * 3600 as time_deff
from rquery_time
order by PRIMARY_MAX_ID;
MAX_DEFF TIME_DEFF
———- ———-
8460 0
4720 0
5360 1
4770 1
4950 0
4240 0
5240 0
6300 1
5040 0
4680 1
两边相差大概5000笔记录,时间延迟在1秒不到的样子,对于37M/S的日志量来说,这个实时性是相当高了
当然备库是否应用跟得上主库,还要看IO的类型和存储的能力,网络传输量,具体环境具体测试
不过使用lgwr+standby logfile传输日志,对于数据的保护理论上只会丢一个async buffer的日志,但实际测试起来,结果会大跌眼镜,
特别是standby机器性能不是很好的情况下很容易发生丢几组日志
我们在32位的AS 4.4上测试出了这个情况,并且可以多次重现
备库跟不上主库的节奏,当前standby logfile 541中的日志还没有全部应用到数据文件,主库已经切换了多次日志
这些日志会以archive log的方式传到备库(如果备库的standby logfile足够的话,会直接使用standby logfile),
如果此时主库突然crash,备库的情况就是
541 standby logfile
542 archive log
543 archive log
理论上可以recover standby database until cancel;然后依次指定上面的文件,但在应用541 standby logfile时,
会遇到非常扯淡的错误(经过旺旺同学解释,数据库是最大性能模式,主库不能保证日志的完全写入,所以是corrupt):
SQL> recover standby database until cancel;
ORA-00279: change 25661117 generated at 07/02/2009 23:38:00 needed for thread 1
ORA-00289: suggestion : /data/oradata/arch/ctrdmsb/ctrdm_1_541_690507562.arc
ORA-00280: change 25661117 for thread 1 is in sequence #541
Specify log: {<RET>=suggested | filename | AUTO | CANCEL}
+DG1/ctrdmsb/redosb_3_1.log
ORA-00283: recovery session canceled due to errors
ORA-00354: corrupt redo log block header
ORA-00353: log corruption near block 421143 change 25661598 time 07/02/2009 23:38:01
ORA-00334: archived log: ‘+DG1/ctrdmsb/redosb_3_1.log’
ORA-01112: media recovery not started
主库意外终止后,oracle会认为当前standby logfile是不可用的,这样会导致后面的两个归档根本没法应用,损失是非常大的