Oracle Goldengate是绝佳的数据实时同步工具,支持各种数据库和常用平台。OGG本身的灵活性加上其内置的大量函数,可以满足DBA各种同步、过滤、转换需求。在OGG的同步逻辑中,数据的来源是数据库的增量日志(对于oracle数据库就是archivelog)。在实际运维中各类故障都好处理,但是一旦源端的归档日志被前提删除,抽取进程报找不到归档日志,这将是特别棘手的问题。特别是归档日志无备份直接delete的情况,简直是运维人员的恶梦!
哪些情况OGG抽取进程需要旧的归档日志呢:
1) 抽取进程abend或stop了一段时间,再次启动自然需要这段时间内的所有归档日志。比如重启了OS或数据库,但忘了启动ogg;长假期间抽取进程abend了无人知晓。
2) 数据库存在迟迟未提交的长事务,时间长了事务的redo信息可能刷到了归档文件中,后面事务提交时抽取进程要扫描这些归档。比如开发人员通过plsqldeveloper修改了表数据,忘了提交;数据库(BI/DW)存在运行比较久的事务或job。
3) OGG bug导致抽取进程需要一个非常旧的归档(可能几年前的)。
抽取进程如何找归档
☆ For classic Extract
OGG优先到数据库默认归档路径查找归档(SELECT THREAD#,SEQUENCE#,FIRST_TIME ,name FROM v$archived_log)。也可以通过参数指定归档查找路径:

加PRIMARY的话就是优先从ALTARCHIVELOGDEST参数路径下是查找。
☆ For Integrated Extract
Integrated Extract原理是由于stream+logminer去抽取数据,每一个抽取进程运行时都有对应的logminer进程在工作,基本是OGG由于数据库字典信息寻找归档所在路径。
如果想指定归档路径,可以使用以下参数(OGG 12.3起)

如何防止归档被删除
一般数据库都有定时备份和清理归档的脚本,我们也是强烈建议归档要rman备份后再删除。这样的话,哪怕归档已被删除,我们仍然可以从备份中恢复再注册回数据库。当然最好能保证抽取进程所需的归档不会删除。但也有很多不备份直接rman清理过去几天归档的情况(本文不讨论直接rm的情况)。
OGG 11.1开始可以通过将经典抽取进程注册到数据库,可以防止rman删除ogg所需的归档。步骤如下:
1) 停止抽取进程
2) 执行以下注册命令

3) 确认抽取进程参数中没有配置TRANLOGOPTIONS LOGRETENTION DISABLED
4) 启动抽取进程
5) 检查抽取进程是否已注册成功

The extract would show up in dba_capture and status would be disabled (if classic & using logretention) and enabled (if IE). The rman integration is default in IE.
实验:如何防止归档被删除
参照以上的命令我们做了LOGRETENTION注册,停止抽取进程,做个大事务,但不提交,试试归档日志能不能删除。

先不提交,我们看到造成了大量的归档日志。

抽取进程先不启动,我们尝试通过rman删除归档,直接报无法删除。

启动抽取进程,过了一会抽取进程就完成抽取。

此时我们再尝试删除归档,还是无法删除。

参照MOS文件Oracle "Capture" and the RMAN-08137 WARNING (文档 ID 1581365.1)的说明:

抽取进程所需的归档同时受V$DATABASE.MIN_REQUIRED_CAPTURE_CHANGE#和DBA_CAPTURE.REQUIRED_CHECKPOINT_SCN影响。

V$DATABASE.MIN_REQUIRED_CAPTURE_CHANGE#是由于抽取进程去负责更新的,默认是每6小时一次。可以通过参数TRANLOGOPTIONS INTEGRATEDPARAMS(_CKPT_RETENTION_CHECK_FREQ XXX)去指定。比如:

我们通过重启下抽取进程也可以触发:

再尝试rman删除成功:



如何减少对归档的依赖
使用Integrated Extract 或者classic Extract +LOGRETENTION,可以防止归档被rman误删除。但是如果数据库有未提交的长事务,还是不得不保留这些归档。
从OGG 11.1开始OGG提供了BR特性,将超过BR周期(4小时)未提交的事务抽取出来缓存到内存和磁盘中。
抽取进程工作时会执行:
1) 抽取进程在redo遇到事务开始时,它开始缓存该事务所有数据到内存中,即使它不是我们要抽取的表,因为该事务的未来操作可能包含要捕获的表数据。
2) 当抽取进程遇到事务提交时,它将整个事务的内存缓存写到trail文件,并从内存中清除它。
3) 当抽取进程遇到事务回滚时,它将从内存中丢弃整个事务。
4) 如果抽取进程在遇到事务的提交或回滚前停止,则当抽取进程启动后要重新提取所有未完成事务信息,必须恢复缓存的信息。
抽取进程启动时会执行:
1) 如果在Extract停止时没有打开的事务,则恢复将从当前提取读取检查点。这是正常恢复。
2) 如果有未完成的事务,并且事务的起点在时间上非常接近到Extract停止的时间为止,Extract通过重新读取redo 归档日志开始恢复。这需要抽取进程对在停止前已经写入trail或丢弃的事务的做重复工作, 但鉴于只有少量数据要处理, 这也是可以接受的
3) 如果有一个或多个事务符合long-running open事务,Extract会从 Bounded Recovery 恢复。
如果事务超过一个Bounded Recovery interval未提交,则会被认为是long-running open事务。由BR参数的BRINTERVAL选项指定(默认4小时),每4小时做一次BR检查点,默认保存在OGG安装目录的BR目录下(由于BRDIR指定)
在每个检查点的时间点上,OGG会检查长事务,并将超过4小时的长事务的状态和数据写入到磁盘(如果没有达到4小时,则此事务不会被BR写入)。
BR的工作原理(简单画个图):

在br checkpoit n 时,假设有t(27)、t(45)、t(801)、t(950)、t(1024) 五个未提交事务,超过4小时的t(27)、t(45)会被br checkpoit n缓存到磁盘
在br checkpoit n+1时,假设t(27)、t(950)、t(1024) 三个事务提交了,t(45)还是未提交,又发生新的变化,会被br checkpoit n+1再次缓存到磁盘,再删除br checkpoit n时的缓存文件,如果t(45)没有变化是不会更新缓存文件的。t(801)是最旧的未提交事务,正常会在br checkpoit n+1做缓存,但如果此时抽取进程停止或崩溃,则t(801)最多需要8个小时的日志来恢复。
因此extract运行时一般需要的归档日志不超过8个小时(极限情况)。当然如果extract停掉后,便无法再自动缓存长事件,需要的归档日志就会依赖于停机时间变长。
BR checkpoit默认就是4小时一次,并保存在OGG_HOME的BR目录下。可以参数手动指定,注意brdir不能使用"temp" or "tmp"字样。

还可以通过手工执行BR检查点,减少恢复所需要使用的归档个数。

实验:如何减少对归档的依赖
抽取进程中不专门指定BR参数,也就是默认就是4小时一次,并保存在OGG_HOME的BR目录下。做个大事务,但不提交,手动触发BR缓存这个事务,然后删除归档日志,测试抽取进程是否正常。

此时BR目录下还没有事务的缓存文件,手动触发BR checkpoint,要触发两次才行,保证事务有经历一个完整的BR interval。这样就看到大量事务的缓存文件。

删除这个事务产生的归档,提交事务,看抽取进程是否正常。

事务提交后,抽取进程有开始工作,但由于空间爆满所以进程abend,清理空间后再次拉起抽取进程,正常工作。

抽取进程追平后,可以看到BR目录事务的缓存文件还在。再次手动触发两次BR checkpoint,经历一次BR interval后缓存文件才会清理掉。


总 结
归档日志是ogg抽取进程的数据来源,意外的归档日志缺失,对抽取进程是一个致命打击。遇到归档丢失的情况,数据可能要重新初始化或者做数据对比和补数。
通过使用Integrated Extract 或者classic Extract +LOGRETENTION,可以防止归档被rman误删除。通过使用BR特性可以减少长事务对归档的依赖。
▼
参考文献
https://docs.oracle.com/cd/E35209_01/doc.1121/e29399.pdf
Oracle "Capture" and the RMAN-08137 WARNING (文档 ID 1581365.1)
GoldenGate LOGRETENTION (文档 ID 1465847.1)
本期作者|马育义 十年老DBA,精通Oracle数据库管理,精通OGG运维,喜欢各种数据库故障和救援处理。同时熟悉mysql、mongodb运维,喜欢钻研各类疑难杂症、技术新动向。持有oracle OCM,ogg OCP, mysql OCP, mongodb认证,AWS SAP认证,阿里云ACP认证等。





