Oracle10gR2 Logical Standby(七)日常管理与优化

有一段时间没怎么写技术性的文章了,继续前面的逻辑备库系列,这是第七篇。

对于逻辑备库来说,日常管理主要需要关注SQL Apply。切换是很少发生的动作,而logminer的速度相对于sql apply来说是很快的,恢复的进度主要还是取决于SQL Apply的进度。

一、SQL Apply进程

SQL Apply实际上是一组后台并行进程,包括reader,preparer,builder,analyzer,coordinator,applier 六种不同作用的进程:

  • reader:读取redo记录传递给preparer进程
  • preparer: 根据redo记录和数据字典信息生成LCR
  • builder: 将同一个事务的LCR打包。对于大事务(eager transaction),可能被打成多个事务包(transaction chunk),那么可能有些包里是不包含commit的,每一个事务包都可能交给不同的applier进程。
  • analyzer:分析事务包之间的依赖关系
  • coordinator:将分析好的事务包交给applier进程
  • applier:将事务包应用,如果事务包依赖其他事务包,则需要等待相应的事务包完成。事务能否commit,可能还需要根据不同的情况从coordinator获得相应的信息。

其中,reader,builder,analyzer和coordinator只能有一个进程,而preparer和applier则可以根据需要开启多个并行进程,但是系统中所有的并行进程不能超过初始化参数parallel_max_servers的限制:

alter database stop logical standby apply;

execute dbms_logstdby.apply_set('PREPARE_SERVERS', 2);
execute dbms_logstdby.apply_set('APPLY_SERVERS', 8);

alter database start logical standby apply;

一般来说,一个preparer进程可以满足20个applier进程的需要。applier的个数,需要根据系统的情况来看,如果所有的applier进程都比较忙碌,可能要考虑增加。简单的可以通过transactions ready和transactions applied两个状态统计来判断,如果两者差值很大,applier进程数可能太少。

SQL> select name,value from v$logstdby_stats where name like 'transactions%';

NAME                           VALUE
------------------------------ -------------
transactions ready             154100
transactions applied           154058

系统中当前已有的preparer和applier进程也可以通过v$logstdby_stats来查询:

SQL> select name,value from v$logstdby_stats where name like 'number%';

NAME                           VALUE
------------------------------ --------------
number of preparers            2
number of appliers              8

各个SQL Apply进程的状态可以通过v$logstdby_process视图获得:

SQL> select sid,type,status from v$logstdby_process;

  SID TYPE         STATUS
----- ------------ --------------------------------------------------------------------------------
 1080 COORDINATOR  ORA-16116: no work available
 1085 READER       ORA-16127: stalled waiting for additional transactions to be applied
 1023 BUILDER      ORA-16127: stalled waiting for additional transactions to be applied
 1025 PREPARER     ORA-16127: stalled waiting for additional transactions to be applied
 1083 PREPARER     ORA-16127: stalled waiting for additional transactions to be applied
 1084 ANALYZER     ORA-16120: dependencies being computed for transaction at SCN 0x0582.1294c01c
 1073 APPLIER      ORA-16124: transaction 57 17 2322872 is waiting on another transaction
 1049 APPLIER      ORA-16124: transaction 44 7 4445763 is waiting on another transaction
 1059 APPLIER      ORA-16124: transaction 59 5 2277932 is waiting on another transaction
 1092 APPLIER      ORA-16124: transaction 13 8 12274153 is waiting on another transaction
 1036 APPLIER      ORA-16124: transaction 2 18 24555358 is waiting on another transaction
 1051 APPLIER      ORA-16124: transaction 45 0 4338376 is waiting on another transaction
 1064 APPLIER      ORA-16124: transaction 56 11 2362783 is waiting on another transaction
 1071 APPLIER      ORA-16113: applying change to table or sequence "NINGOO"."TEST"
 

从这里可以看到,由于存在一个大事务,大部分applier进程都在等待1071事务的完成,这样应用日志的效率就非常低下。从实际情况来看,大事务对于逻辑备库的影响是非常大的,主库一条语句更新1000行,到逻辑备库就需要解析出1000条语句逐条执行,如果这个表没有主键,那么这些语句甚至需要走全表扫描,那代价就更高了,你会发现一个事务,也许一个小时都未必能应用完成。要在产品环境中使用逻辑备库,一定要想办法打散大事务。

逻辑备库上当前执行的事务可以从v$transaction中获得,然后通过关联v$session和v$sqlarea可以获得事务的SQL语句,进来获得执行计划。

二、LCR Cache

逻辑备库需要将redo记录解析成LCR,会在shared pool里分配一部分空间来作为LCR Cache,如果cache太小,就会像OS的虚拟内存管理一样,需要做page out,这会严重影响应用日志的性能。曾经碰到过这么一个案例,由于存在一个比较大的事务,跨越了5个logfile,逻辑备库重启后,需要从最早一个没有commit的事务开始重新读取解析和应用日志,因为LCR Cache太小,重新分析这5个logfile的时候产生了大量的page out,即使只需要应用这一个事务,每解析一个日志都花了将近半个小时。后来将LCR Cache增加,一个日志只花了一分钟不到。

默认情况下,LCR Cache为Shared pool的四分之一,最少不少于30M,否则SQL Apply不能启动。如果机器的内存足够,建议将LCR Cache尽量设大一点,当然,同时share pool也要足够大。如果机器内存有限,那可以考虑将buffer cache减少一点来给LCR Cache腾出空间。

下面的语句将LCR cache设置为1000M:

alter database stop logical standby apply;

EXECUTE DBMS_LOGSTDBY.APPLY_SET('MAX_SGA', 1000);

alter database start logical standby apply;

可以根据系统中page out的情况来调整LCR Cache的大小:

SQL> select name,value from v$logstdby_stats where name like '%page%';

NAME                           VALUE
------------------------------ --------------
bytes paged out                0
seconds spent in pageout       0

如果LCR Cache设置太大也是浪费,下面的SQL可以查询其使用率:

select name,(least(max_sga,bytes)/max_sga) * 100 pct_utilization
from ( select * from v$sgastat where name = 'Logminer LCR c'
),
(select value*(1024*1024) max_sga from dba_logstdby_parameters
where name = 'MAX_SGA'
);

NAME                           PCT_UTILIZATION
------------------------------ ---------------
Logminer LCR c                             100

三、忽略不需要应用日志的对象

逻辑备库一般是用来做报表,或者做读写分离来分担主库的读压力。对于很多系统,实际上不需要将主库上所有对象的变更都应用到逻辑备库上。比如OLTP上可能有些表是定期从数据仓库里回流过来的,这些表在数据仓库中都已经存在,没有必要到逻辑备库上查询。而且这些回流的表一般都是通过批量的方式拉过来的,都是大事务,对于逻辑备库的性能有很大的影响,那么能在逻辑备库上忽略掉是最好的了。注意参数需要大写。

alter database stop logical standby apply;

--忽略某个表上的DML
execute dbms_logstdby.skip (stmt => 'DML', schema_name => 'HR', 
 object_name => 'EMPLOYEES', proc_name => null);
--忽略某个表上的DDL
execute dbms_logstdby.skip (stmt => 'SCHEMA_DDL', schema_name => 'HR', 
 object_name => 'EMPLOYEES', proc_name => null);
--忽略某个Schema的DML
execute dbms_logstdby.skip (stmt => 'DML', 
 schema_name => 'NINGOO', object_name => '%', proc_name => null);
--忽略某个Schema的DDL
execute dbms_logstdby.skip (stmt => 'SCHEMA_DDL', 
 schema_name => 'NINGOO', object_name => '%', proc_name => null);
           
alter database start logical standby apply;

四、事务一致性

逻辑备库在恢复的过程中,可以设置不同的事务一致性级别,一共有三种(9i):

  • Full:这是默认的级别,事务应用的顺序和主库完全一致
  • Read Only:这个级别的性能要比full好一些,并且对于select等到的数据还是一致的。但是事务在应用过程中可能和主库中commit的顺序是不一致的。
  • NONE:完全不管主库的事务顺序,这个级别性能最好,但是可能读取到不一致的数据。
alter database stop logical standby apply;

exec dbms_logstdby.apply_set('TRANSACTION_CONSISTENCY','READ_ONLY');

alter database start logical standby apply;

Oracle10gR2已经不建议使用TRANSACTION_CONSISTENCY,而是使用另外一个替代参数PRESERVE_COMMIT_ORDER,设置为TRUE相当于TRANSACTION_CONSISTENCY=FULL,而设置设置为FALSE相当于TRANSACTION_CONSISTENCY=NONE,而READ_ONLY模式在10g实际上已经被取消了(Metalink:387450.1)。据文档说PRESERVE_COMMIT_ORDER=FALSE可以提升应用日志50%的性能,但不保证此时读取的数据是一致的。

五、自动删除已经应用过的日志

默认情况下,SQL Apply会在日志应用完成,并且日志涉及到的事务都已经全部commit的情况下,自动删除日志。因为逻辑备库一方面需要接收主库传过来的日志,一方面自己也会产生日志,不及时删除,可能很快归档空间就要爆掉了。

这个行为也可以通过修改apply的参数来改变:

alter database stop logical standby apply;

execute dbms_logstdby.apply_set('LOG_AUTO_DELETE', FALSE);

alter database start logical standby apply;

六、更改logminer的默认表空间

逻辑备库使用logminer技术来获取logfile中的redo记录,logminer需要保存很多的元数据,在10gR2中,logminer默认使用sysaux表空间。一般的系统中,sysaux都不会给太大,可能很快就被logminer撑爆了,可以考虑修改logminer的默认表空间:

exec DBMS_LOGMNR_D.set_tablespace('TBS_NINGOO_DAT');


无觅相关文章插件,快速提升流量

没有评论


(Required)
(Required, will not be published)