一、文章概述
本篇文章是针对Ogg19.1集成模式复制进程延迟高问题进行分析并处理的过程。
备注:常规的OGG复制进程慢基本上也可以按照这个套路。
二、问题分析
2.1 SQL执行慢
2.1.1.问题现象
巡检发现进程存在延迟
GGSCI>info all Program Status Group Lag at Chkpt Time Since Chkpt REPLICAT RUNNING REPAP01 00:12:56 00:19:34
复制
OGG Time Since Chkpt代表OGG这个进程有19分钟没有commit提交数据,也代表了这个进程同步Dml操作时间很长,可能存在性能问题。
–备注有需要了了解两个Chkpt的说明可以看看如下博客链接
https://www.cnblogs.com/lvcha001/p/13469500.html
复制
2.1.2.定位问题
可以使用查询session脚本定位OGG会话执行什么SQL?
replicat@xxxdb1 (TN 403 14281 C##OGG oracle 0ajv7pxmcjduc xxdb1 ACTIVE 15 15:42:02 CPU
复制
多次执行session.sql脚本,发现这个replicat OGG复制进程,一直在执行SQL_ID 0ajv7pxmcjduc ,当查询多次也就是同一个SQL执行>3s的复制,需要关注!!!
这个脚本也没啥特殊的,就是查询active session exec sql_id or event,如果大家需要排查OGG的问题,加上username=’$OGG_USER’这样更快
2.1.3.查询SQL执行计划
select * from table(dbms_xplan.display_cursor(‘0ajv7pxmcjduc’));
通过执行计划,可以看到这个OGG执行delete操作,执行计划全表扫描!执行效率非常低!!!
2.1.4.优化SQL
当遇到是OGG复制进程执行的SQL性能问题时,优化思路与优化SQL类似!
1.收集统计信息;
EXEC dbms_stats.gather_table_stats (ownname=>'Cxx',TABNAME=>'Nxx', CASCADE=>TRUE,DEGREE=>16,ESTIMATE_PERCENT=>3,NO_INVALIDATE=>false);
复制
2.添加主键字段
select b.INDEX_OWNER,b.INDEX_NAME,b.INVALID, a.COLUMN_NAME,b.CONSTRAINT_TYPE, b.STATUS,b.CONSTRAINT_NAME from dba_cons_columns a,dba_constraints b where a.owner=b.owner and a.owner='Cxx' and b.TABLE_NAME=a.TABLE_NAME and a.table_name='Nxx' and a.CONSTRAINT_NAME=b.CONSTRAINT_NAME; ------------------------------------ &OWNER &NAME ROW_ID C ENABLED SYS_C00135314
复制
–这个表是ROWID字段同步的表,但是没有主键或唯一约束,但是实际知道这个ROW_ID字段记录的是源库rowid值是唯一的,可以放心添加主键约束!
alter table Cxx.NGLxxNCES add constraint pk_rowid_xxES unique (row_id) enable Novalidate;
复制
#注意生产环境使用默认enable添加主键需要慎重! enable Novalidate能极大加速添加主键的时间,而非默认会锁很长时间的表,影响业务。
添加主键成功后,检查
select b.INDEX_OWNER,b.INDEX_NAME,b.INVALID, a.COLUMN_NAME,b.CONSTRAINT_TYPE,b.STATUS, b.CONSTRAINT_NAME from dba_cons_columns a,dba_constraints b where a.owner=b.owner and a.owner='Cxx' and b.TABLE_NAME=a.TABLE_NAME and a.table_name='NGLxx' and a.CONSTRAINT_NAME=b.CONSTRAINT_NAME and b.CONSTRAINT_TYPE='U';
复制
3.细粒度对表DDL操作
–收集统计信息后,OGG复制执行的SQL执行计划没有改变,对表DDL,让SQL硬解析
comment on table xx.xx is 'ogg_big_tab'; select owner,to_char(LAST_DDL_TIME,'yyyy-mm-dd hh24:mi:ss') from dba_objects where object_name='xx'; ------------------------------------------------------------ xx 2021-11-14 02:54:45
复制
由于只是修改表的注释,所以实际操作是毫秒级别,不会像其它DDL操作执行几分钟、甚至几个小时阻塞业务正常DML操作。
4.使用参数keycols
这个套路一般使用在目标端没有主键字段的情况下,直接使用选择性好的字段修改ogg参数配置
MAP FPxx.xxxL.xxxx,TARGET OGxx.GxxxS ,colmap (usedefaults , ROW_ID= @token ('TKN-ROWID')),keycols(ROW_ID);
复制
5.手工设置加大全表扫描Cost
一般普通的SQL性能慢导致的OGG延迟高,使用上述套路基本上都解决了,但是本次这个问题比较有意思上述套路都没解决,那么统计信息是准确的,有主键字段Oracle还是不走索引! 那么思路就是说Oracle对rowid_id字段的Cost成本计算我认为可能不准确。 那么既然Oracle已经没有办法使用正常的Cost成本计算出正确的执行计划,走rowid对应的主键列索引,那么我们手工修改表的cost成本,让Oracle统计到走索引cost更低!
--手工修改统计信息 begin dbms_stats.set_table_stats(ownname=>'CxxL', tabname=>'NGLxx', numrows=>999999999999999999999, numblks=>8, avgrlen=>'800'); end; / SQL> select NUM_ROWS,BLOCKS,EMPTY_BLOCKS, to_char(LAST_ANALYZED,'yyyy-mm-dd hh24:mi:ss') from dba_tables where TABLE_NAME='NGxx'; NUM_ROWS BLOCKS EMPTY_BLOCKS TO_CHAR(LAST_ANALYZ ---------- ---------- ------------ ------------------- 1.0000E+21 8 0 2021-11-15 16:06:42
复制
建议手工收集统计信息后,对该表统计信息进行Lock,否则下一次再次收集统计信息会刷出手工设置的值,那么OGG进程执行的SQL下一次解析可能会再次选择慢的执行计划!!!
exec dbms_stats.lock_table_stats('Cxx','NGL_FAxx'); col table_name for a20 select table_name,stattype_locked from dba_tab_statistics where table_name='xxS'; TABLE_NAME STATT --------------------------------------------- NGxxx ALL
复制
!!!注意:建议这种优化套路,只针对OGG同步的表,因为本次优化设计的表dba_indexes没有查询到索引,这种情况下,手工修改cost没什么影响!
反之,如果业务表存在多个索引,手工修改加大表 cost,那么Oracle可能会走效率很低的索引,而不选择全表扫描!!!
另一种思路,只针对rowid同步的字段表,可以减小rowid字段索引的cost成本,因为rowid 字段只是为了OGG进行目标端数据同步,修改表会影响表的所有相关cost对比,但是你只修改rowid字段的影响更小。但是我们本次遇到的场景直接改表就行了。
2.1.5.优化后效果
2.2 同步的数据多
也就是OGG现有的进程模式无法快速处理所有的OGG Trail的日志同步,这个和服务器IO内存CPU也有一定关系,和OGG版本模式也有关系,但是这个都不是本次讨论的重点。现在的问题是OGG单个复制进程处理数据忙不过来? 怎么处理!
2.2.1.问题现象
巡检发现进程存在延迟
GGSCI>info all Program Status Group Lag at Chkpt Time Since Chkpt REPLICAT RUNNING RExx1 00:50:06 00:00:00
复制
巡检发现Time Since Chkpt的延迟很低,可以说明OGG一直在同步数据,但是整体的执行效率低,导致OGG同步的最后时间和源库延迟了50分钟!!!
这个延迟的时间对大部分业务来说可能并不能接受,需要关注并处理。
2.2.2.问题分析
select to_char(SAMPLE_TIME,'yyyy-mm-dd hh24') as "date", event,count(*) from v$active_session_history where SAMPLE_TIME between to_date('20211115 13:00','yyyymmdd hh24:mi') and to_date('20211115 18:00','yyyymmdd hh24:mi') and CON_ID='3' and user_id=108 and PROGRAM like '%oracle@ebxxx1%' group by to_char(SAMPLE_TIME,'yyyy-mm-dd hh24'),event having(count(*))>10 order by 1,3,2;
复制
通过对OGG进程的几个小时汇总,可以发现 null =on cpu sql exec的执行占比最高,没有异常的等待事件!
select sql_id,count(*) from v$active_session_history where SAMPLE_TIME between to_date('20211115 13:00','yyyymmdd hh24:mi') and to_date('20211115 18:00','yyyymmdd hh24:mi') and CON_ID='3' and user_id=108 and PROGRAM like '%oracle@ebxxb1%' group by sql_id having(count(*))>10 order by 2;
复制
SQL维护汇总,并没有看到什么慢的SQL,唯一一个捕获200次统计的SQL还是修改数据字典,可以忽略!
汇总:通过上述信息汇总得到的结果,就是说OGG复制进程并没有慢的SQL或者异常的等待事件导致进程延迟。 纯粹是OGG单个进程需要读取同步的数据多,导致单个进程忙不过来!!!
2.2.3.问题处理
如何提升单个进程的处理速度,或者降低单个进程的延迟?
1.进程拆分,让OGG一个复制进程需要处理的trail日志变少,从而降低延迟;
2.进程设置并行参数,让原本一个session处理的工作,提高到多个session一起处理,从而提升单个进程处理的能力,降低单个进程的执行时间;
3.*本次处理效果不明显,使用OGG参数,对小事务进行合并成大事务,从而降低commit时间,提高进程处理速度,本次场景效果不大!
批处理参数,如下都尝试无效果 BATCHSQL BATCHESPERQUEUE 20,OPSPERBATCH 8000 BATCHSQL BATCHESPERQUEUE 800,OPSPERBATCH 80000 BATCHSQL BATCHESPERQUEUE 100, BATCHTRANSOPS 10000 , OPSPERBATCH 10000, OPSPERQUEUE 100000
复制
2.2.3.1.进程拆分
找到DML变换多的表清单
思路就是找到DML变换最多的top 表,从里面选择几个top表放到新的复制进程,这样原来延迟高的复制进程减少了几个变换最多的表数据从而加快,而全新的复制进程由于只同步几个所以整体来看速度都加快了,延迟问题得到解决。
ggsci >/tmp/stats_20211115.log <<EOF
info REPAP01
stats REPAP01
exit
EOF
将DML操作汇总变换大于1w的进行汇总,实际情况就是选择top 选择几个对象!将这些经常变换的表,迁移到新的进程中,原来的延迟高的进程对这些迁移的表进行删除不在同步。
举例如下: Replicating from PROD.GL.GL_JE_LINES to Fxx.CxxL.NGL_FxxS: Total operations 45827.00
复制
进程参数编辑
>edit param REPAP02 REPLICAT repap02 USERIDALIAS ExxOGG ASSUMETARGETDEFS GETTRUNCATES DBOPTIONS NOSUPPRESSTRIGGERS DBOPTIONS DEFERREFCONST report at 1:59 reportrollover at 2:00 reperror default,abend ALLOWNOOPUPDATES INSERTMISSINGUPDATES DISCARDFILE ./dirrpt/discard_repap02.dsc, PURGE MAP Pxx,TARGET CxxS,FILTER (@GETENV('TRANSACTION','CSN') > 894300384284);
复制
进程添加
--add NEW_OGGPRO=repap02 NEW_OGG_FILE=repap01/pa ggsci <<EOF dblogin USERIDALIAS ExxG add checkpointtable C##OGG.${NEW_OGGPRO}_ckp_tab2 add replicat $NEW_OGGPRO ,integrated ,exttrail ./dirdat/${NEW_OGG_FILE},CHECKPOINTTABLE C##OGG.${NEW_OGGPRO}_ckp_tab2 register replicat ${NEW_OGGPRO} database exit EOF
复制
新建进程启动
关闭原延迟高的复制进程
GGSCI>stop repap01 --确认进程stop REPLICAT STOPPED REPAP01 00:57:40 00:03:49 REPLICAT STOPPED REPAP02 00:00:00 00:00:06
复制
–查询延迟高的复制进程最后一个时间点rba
GGSCI (xxb1) 2> info REPAP01 REPLICAT REPAP01 Last Started 2021-11-15 17:21 Status STOPPED INTEGRATED Checkpoint Lag 00:57:40 (updated 00:03:58 ago) Log Read Checkpoint File ./dirdat/repap01/pa000000015 2021-11-15 16:37:10.851420 RBA 46286994
复制
–修改新的复制进程,从延迟高的进程最后一个rba开始进行同步
alter REPLICAT REPAP02 ,extseqno 15,extrba 46286994
复制
–检查
GGSCI (ebsfiproddb1) 5> info REPAP02 REPLICAT REPAP02 Initialized 2021-11-15 17:39 Status STOPPED INTEGRATED Checkpoint Lag 00:00:00 (updated 00:00:05 ago) Log Read Checkpoint File ./dirdat/repap01/pa000000015 First Record RBA 46286994
复制
–启动新建的复制进程
GGSCI (exx1) 3> start REPAP02
复制
延迟高进程启动
延迟高的复制进程,在确认新建的复制进程正常同步后,删除新的复制进程同步的表,避免重复同步!!!
$ cat repap01.prm |grep GL_xx $ cat repap02.prm |grep GL_xx 确认新建的复制进程正常复制后,删除延迟高的复制进程对应拆分的表后,启动之前stop的复制进程 --删除后,启动复制进程 GGSCI (ebsfiproddb1) > start REPAP01
复制
2.2.3.2.进程启用并行
参考OGG Parallel
Parallelism Off ● Offers maximum safety – works like Classic Replicat – Does not start a following transaction before committing the current transaction – Always using the “parallel style” checkpoint table -– Even when working with just 1 apply session – Used for “large transactions” ● Integrated Replicat: – DBOPTIONS INTEGRATEDPARAMS (PARALLELISM 1) – Automatically sets: GROUPTRANSOPS 25 ● Parallel Nonintegrated Replicat: – APPLY_PARALLELISM 1 – or: COMMIT_SERIALIZATION ● Parallel Integrated Replicat: – APPLY_PARALLELISM 1
复制
本次选用● Integrated Replicat
编辑参数
复制进程添加参数
DBOPTIONS INTEGRATEDPARAMS(parallelism 24)
复制
巡检发现OGG复制进程还是存在2分钟左右的延迟,生产环境不太建议延迟较高。并且考虑到后续月结等导致OGG同步数据更多导致延迟加剧,最终影响性能。
优化后效果
REPLICAT RUNNING REPAP01 00:00:09 00:00:00 REPLICAT RUNNING REPAP02 00:00:00 00:00:04
复制
处理之后OGG在下午业务高峰期观察延迟,只有短时间内有2分钟,随后延迟降低到10s内,可以接受。
复制
优化对数据库影响
后续给客户看了之后,客户担心月结或者年结再次出现问题,后续就是找到OGG历史的stats的记录,对复制进程拆分新增4个,更进一步的进行了拆分。 本次OGG可以认为源端抽取投递是一个进程,复制一个进程拆分为5个!
这个OGG是支持的,但是需要注意可能产生的另一个问题,之前有客户环境遇到一次多个复制进程同时应用投递过来的一个trail文件;其中一个OGG进程由于某些问题hang住了,recover ckpt不往前走,虽然看起来current ckpt向前,但是recover ckpt不往前走,导致MGR不删除trail文件,最终导致OGG trail文件对应的操作系统空间满,所有进程受到影响! 每次手工删除费时费力!最后对有问题的进程重建后问题解决。
三、结论及建议
1.使用监控软件等方式,实现邮件或者短信、微信等实时告警。
当OGG进程ABEND; 或者OGG延迟达到一定时间,例如10分钟、30分钟、60分钟实现监控告警,运维人员及时处理。
2.如何从源头避免OGG产生性能问题呢???
对所有同步OGG的表,在源库就改造都有主键或者唯一约束的字段情况,好处多多
对于主键或者唯一字段的OGG同步的表,源端添加表最小补充日志不在是全列添加!减少了trail文件的记录;目标库OGG 复制执行dml操作使用主键或唯一约束列对应的索引更快的执行update or delete效率有保障,以及由于传输过来的trail日志变少,执行效率理论上更快。
在数据初始化后,及时收集统计信息,否则大表非常容易全表扫描导致OGG复制进程慢!
评论

