在早期的 OGG 版本中,如果要监控进程的延迟状态,需要手工创建心跳表, OGG12.2 开始后,通过简单配置就可以启用心跳表监控功能。
下面我们将演示如何配置OGG12.2版本前后的心跳表,以及一些简单的应用。
12.2之前的版本配置
在 12.2 之前的 GoldenGate 心跳的实现需要修改以下应用程序和数据库。
Ø 向源GoldenGate 数据库 用户下 添加心跳表 ( HEARTBEAT )
Ø 向 目标 GoldenGate 数据库 用户下 添加一个 心跳 状态表 ( GGS_HEARTBEAT ) 和一个历史表 ( GGS_HEARTBEAT_HISTORY )
Ø 向每个 进程 添加 心跳表 映射语句
Ø 在源数据库上创建一个DBMS 调度器作业来更新心跳表。
源和目标 的 心跳表具有相同的结构。在源系统中,心跳是单个的时间戳的行更新。 抽取进程 将提取更新的信息,并向记录添加两个 token 。该信息被写入 trail 文件 中,以供后续进程在 讲 记录通过 传输进程 并 写入 目标时读取和添加附加信息 。
在目标系统上,第一条记录将被插入到心跳 状态 表中,然后再插入到历史表中。 后续的记录将 更新状态表中的 该 记录并将其插入历史表中。当插入记录时,额外的信息将通过 token 添加到表中 ,以及通过 触发器自动计算每条记录的延迟 并 添加到心跳表中。
1. 用户创建(源和目标)
为了创建源表和目标表,源表和目标表都需要 用户 。 如果已经有 ogg 同步在跑, 建议您使用GoldenGate 管理 用户。
注意:如果这是一个排除GoldenGate 管理 用户的双向配置,则需要在 其他用户下 中创建源心跳表。目标表可以在GoldenGate 用户下 。
如果不想使用 ogg 管理用户,则可以使用下面语句创建相应用户,名字可自己更改。
源端数据库 SQL> create user source identified by ggs; SQL> grant connect, resource, dba to source; 目标端数据库 SQL> create user target identified by ggs; SQL> grant connect, resource, dba to target;
本文我们用原有 ogg 的管理用户,ogg112(源库和目标库都已经有该用户)。
2 . 心跳表创建(源和目标)
在 本次 配置中,我们 会 使用 到 三个心跳表 : heartbeat 、 GGS_HEARTBEAT 和 GGS_HEARTBEAT_HISTORY 。所有的表都有相同的 表结构 ,但用于不同的信息。
HEARTBEAT 表中可能有不止一行,这取决于线程(RAC )的数量,并且只更新 Update_timestamp 列 和 SRC_DB 列 。在目标系统上,GGS_HEARTBEAT 表包含映射到该心跳的所有副本的当前(最后一次更新)心跳。最后一个表是GGS_HEARTBEAT_HISTORY 表,所有的心跳记录都插入到该历史表中。此表可用于显示一个过程在一段时间内的延迟。在生产环境中,我们可以对该表进行分区,方便后续对该表的维护。
心跳表表结构如下:
|
Column Contents | |
|
ID |
Sequence number |
|
SRC_DB |
Source Database Name |
|
Extract_name |
Name of the extract process from token. |
|
Source_commit |
Source commit timestamp from header. |
|
Target_commit |
When the record was added to the target. This is updated by the trigger. |
|
CAPTIME |
Added as a token using DATANOW() function. |
|
CAPLAG |
Capture time – commit time on the source. This is updated by the trigger |
|
PMPTIME |
When token timestamp was added to trail in the data pump using DATENOW() |
|
PMPGROUP |
Data pump group name. |
|
PMPLAG |
Capture time minus the time that the record was passed thru the data pump. Value is calculated by the update trigger. |
|
DELTIME |
This is added as part of the map statement using DATENOW(). |
|
DELGROUP |
Name of the replicat group. |
|
DELLAG |
The defference between the time the record was passed thry the data pump and when the record was inserted into the target table. This is calculated in the trigger. |
|
TOTALLAG |
The difference between the target commit time and the source commit time. This is updated via the trigger. |
|
Thread |
Thread number from instance. |
|
Update_timestamp |
The system time of the update into the HB table. |
|
EDDLDELTASTATS |
DDL operations since the last gathering (Delta) of stats on the extract process. |
|
EDMLDELTASTATS |
DML operations since the last gathering (Delta) of stats on the extract process. |
|
RDDLDELTASTATS |
DDL operations since the last gathering (Delta) of stats on the replicat process. |
|
RDMLDELTASTATS |
DML operations since the last gathering (Delta) of stats on the replicat process. |
可以通过 heartbeat_tables_v11.sql 脚本来创建这些心跳表并向其中插入记录。(该脚本完成内容查看文档末尾附件)。
如果直接采用脚本创建,则可以使用如下命令:
SQL> @<path>/heartbeat_tables_v11.sql
注意: heartbeat_tables_v11.sql 脚本包括三部分信息
1. HEARTBEAT 表的创建
2. GGS_HEARTBEAT 表和 GGS_HEARTBEAT_TRIG 触发器的创建
3. GGS_HEARTBEAT_HISTORY 表和 GGS_HEARTBEAT_TRIG_HIST 触发器的创建
其中触发器主要用于添加和计算 ID , target_COMMIT , CAPLAG , PMPLAG , DELLAG 和 TOTALLAG 列的数值。
偷懒的方法可以直接在源端和目标端跑该脚本,但是如果不想在源端创建触发器,则在源端只需要创建 HEARTBEAT 表,在目标端创建 GGS_HEARTBEAT 、 GGS_HEARTBEAT_HISTORY 表和 GGS_HEARTBEAT_TRIG 、 GGS_HEARTBEAT_TRIG_HIST 触发器。
源端 heartbeat_tables_v11.sql 脚本保留:
accept ogg_user prompt 'GoldenGate User name:' drop table &&ogg_user..heartbeat; -- Create table statement CREATE TABLE &&ogg_user..HEARTBEAT ( ID NUMBER , SRC_DB VARCHAR2(30), EXTRACT_NAME varchar2(8), SOURCE_COMMIT TIMESTAMP, TARGET_COMMIT TIMESTAMP, CAPTIME TIMESTAMP, CAPLAG NUMBER, PMPTIME TIMESTAMP, PMPGROUP VARCHAR2(8 BYTE), PMPLAG NUMBER, DELTIME TIMESTAMP, DELGROUP VARCHAR2(8 BYTE), DELLAG NUMBER, TOTALLAG NUMBER, thread number, update_timestamp timestamp, EDDLDELTASTATS number, EDMLDELTASTATS number, RDDLDELTASTATS number, RDMLDELTASTATS number, CONSTRAINT HEARTBEAT_PK PRIMARY KEY (SRC_DB) ENABLE ) / -- this assumes that the table is empty INSERT INTO &&ogg_user..HEARTBEAT (SRC_DB) select db_unique_name from V$database; commit;
执行该脚本,或直接修改上面用户执行 sql 都可。
目标端 heartbeat_tables_v11.sql 脚本保留:
DROP SEQUENCE &&ogg_user..SEQ_GGS_HEARTBEAT_ID ; CREATE SEQUENCE &&ogg_user..SEQ_GGS_HEARTBEAT_ID INCREMENT BY 1 START WITH 1 ORDER ; DROP TABLE &&ogg_user..GGS_HEARTBEAT; CREATE TABLE &&ogg_user..GGS_HEARTBEAT ( ID NUMBER , SRC_DB VARCHAR2(30), EXTRACT_NAME varchar2(8), SOURCE_COMMIT TIMESTAMP, TARGET_COMMIT TIMESTAMP, CAPTIME TIMESTAMP, CAPLAG NUMBER, PMPTIME TIMESTAMP, PMPGROUP VARCHAR2(8 BYTE), PMPLAG NUMBER, DELTIME TIMESTAMP, DELGROUP VARCHAR2(8 BYTE), DELLAG NUMBER, TOTALLAG NUMBER, thread number, update_timestamp timestamp, EDDLDELTASTATS number, EDMLDELTASTATS number, RDDLDELTASTATS number, RDMLDELTASTATS number, CONSTRAINT GGS_HEARTBEAT_PK PRIMARY KEY (DELGROUP) ENABLE ); CREATE OR REPLACE TRIGGER &&ogg_user..GGS_HEARTBEAT_TRIG BEFORE INSERT OR UPDATE ON &&ogg_user..GGS_HEARTBEAT FOR EACH ROW BEGIN select seq_ggs_HEARTBEAT_id.nextval into :NEW.ID from dual; select systimestamp into :NEW.target_COMMIT from dual; select trunc(to_number(substr((:NEW.CAPTIME - :NEW.SOURCE_COMMIT ),1,instr(:NEW.CAPTIME - :NEW.SOURCE_COMMIT,' ')))) * 86400 + to_number(substr((:NEW.CAPTIME - :NEW.SOURCE_COMMIT), instr((:NEW.CAPTIME - :NEW.SOURCE_COMMIT),' ')+1,2)) * 3600 + to_number(substr((:NEW.CAPTIME - :NEW.SOURCE_COMMIT), instr((:NEW.CAPTIME - :NEW.SOURCE_COMMIT),' ')+4,2) ) * 60 + to_number(substr((:NEW.CAPTIME - :NEW.SOURCE_COMMIT), instr((:NEW.CAPTIME - :NEW.SOURCE_COMMIT),' ')+7,2)) + to_number(substr((:NEW.CAPTIME - :NEW.SOURCE_COMMIT), instr((:NEW.CAPTIME - :NEW.SOURCE_COMMIT),' ')+10,6)) / 1000000 into :NEW.CAPLAG from dual; select trunc(to_number(substr((:NEW.PMPTIME - :NEW.CAPTIME),1, instr(:NEW.PMPTIME - :NEW.CAPTIME,' ')))) * 86400 + to_number(substr((:NEW.PMPTIME - :NEW.CAPTIME), instr((:NEW.PMPTIME - :NEW.CAPTIME),' ')+1,2)) * 3600 + to_number(substr((:NEW.PMPTIME - :NEW.CAPTIME), instr((:NEW.PMPTIME - :NEW.CAPTIME),' ')+4,2) ) * 60 + to_number(substr((:NEW.PMPTIME - :NEW.CAPTIME), instr((:NEW.PMPTIME - :NEW.CAPTIME),' ')+7,2)) + to_number(substr((:NEW.PMPTIME - :NEW.CAPTIME), instr((:NEW.PMPTIME - :NEW.CAPTIME),' ')+10,6)) / 1000000 into :NEW.PMPLAG from dual; select trunc(to_number(substr((:NEW.DELTIME - :NEW.PMPTIME),1, instr(:NEW.DELTIME - :NEW.PMPTIME,' ')))) * 86400 + to_number(substr((:NEW.DELTIME - :NEW.PMPTIME), instr((:NEW.DELTIME - :NEW.PMPTIME),' ')+1,2)) * 3600 + to_number(substr((:NEW.DELTIME - :NEW.PMPTIME), instr((:NEW.DELTIME - :NEW.PMPTIME),' ')+4,2) ) * 60 + to_number(substr((:NEW.DELTIME - :NEW.PMPTIME), instr((:NEW.DELTIME - :NEW.PMPTIME),' ')+7,2)) + to_number(substr((:NEW.DELTIME - :NEW.PMPTIME), instr((:NEW.DELTIME - :NEW.PMPTIME),' ')+10,6)) / 1000000 into :NEW.DELLAG from dual; select trunc(to_number(substr((:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT),1, instr(:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT,' ')))) * 86400 + to_number(substr((:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT), instr((:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT),' ')+1,2)) * 3600 + to_number(substr((:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT), instr((:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT),' ')+4,2) ) * 60 + to_number(substr((:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT), instr((:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT),' ')+7,2)) + to_number(substr((:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT), instr((:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT),' ')+10,6)) / 1000000 into :NEW.TOTALLAG from dual; end ; / ALTER TRIGGER &&ogg_user..GGS_HEARTBEAT_TRIG ENABLE; -- -- This is for the History heartbeat table -- DROP SEQUENCE &&ogg_user..SEQ_GGS_HEARTBEAT_HIST ; CREATE SEQUENCE &&ogg_user..SEQ_GGS_HEARTBEAT_HIST INCREMENT BY 1 START WITH 1 ORDER; DROP TABLE &&ogg_user..GGS_HEARTBEAT_HISTORY; CREATE TABLE &&ogg_user..GGS_HEARTBEAT_HISTORY ( ID NUMBER , SRC_DB VARCHAR2(30), EXTRACT_NAME varchar2(8), SOURCE_COMMIT TIMESTAMP, TARGET_COMMIT TIMESTAMP, CAPTIME TIMESTAMP, CAPLAG NUMBER, PMPTIME TIMESTAMP, PMPGROUP VARCHAR2(8 BYTE), PMPLAG NUMBER, DELTIME TIMESTAMP, DELGROUP VARCHAR2(8 BYTE), DELLAG NUMBER, TOTALLAG NUMBER, thread number, update_timestamp timestamp, EDDLDELTASTATS number, EDMLDELTASTATS number, RDDLDELTASTATS number, RDMLDELTASTATS number ); CREATE OR REPLACE TRIGGER &&ogg_user..GGS_HEARTBEAT_TRIG_HIST BEFORE INSERT OR UPDATE ON &&ogg_user..GGS_HEARTBEAT_HISTORY FOR EACH ROW BEGIN select seq_ggs_HEARTBEAT_HIST.nextval into :NEW.ID from dual; select systimestamp into :NEW.target_COMMIT from dual; select trunc(to_number(substr((:NEW.CAPTIME - :NEW.SOURCE_COMMIT ),1, instr(:NEW.CAPTIME - :NEW.SOURCE_COMMIT,' ')))) * 86400 + to_number(substr((:NEW.CAPTIME - :NEW.SOURCE_COMMIT), instr((:NEW.CAPTIME - :NEW.SOURCE_COMMIT),' ')+1,2)) * 3600 + to_number(substr((:NEW.CAPTIME - :NEW.SOURCE_COMMIT), instr((:NEW.CAPTIME - :NEW.SOURCE_COMMIT),' ')+4,2) ) * 60 + to_number(substr((:NEW.CAPTIME - :NEW.SOURCE_COMMIT), instr((:NEW.CAPTIME - :NEW.SOURCE_COMMIT),' ')+7,2)) + to_number(substr((:NEW.CAPTIME - :NEW.SOURCE_COMMIT), instr((:NEW.CAPTIME - :NEW.SOURCE_COMMIT),' ')+10,6)) / 1000000 into :NEW.CAPLAG from dual; select trunc(to_number(substr((:NEW.PMPTIME - :NEW.CAPTIME),1, instr(:NEW.PMPTIME - :NEW.CAPTIME,' ')))) * 86400 + to_number(substr((:NEW.PMPTIME - :NEW.CAPTIME), instr((:NEW.PMPTIME - :NEW.CAPTIME),' ')+1,2)) * 3600 + to_number(substr((:NEW.PMPTIME - :NEW.CAPTIME), instr((:NEW.PMPTIME - :NEW.CAPTIME),' ')+4,2) ) * 60 + to_number(substr((:NEW.PMPTIME - :NEW.CAPTIME), instr((:NEW.PMPTIME - :NEW.CAPTIME),' ')+7,2)) + to_number(substr((:NEW.PMPTIME - :NEW.CAPTIME), instr((:NEW.PMPTIME - :NEW.CAPTIME),' ')+10,6)) / 1000000 into :NEW.PMPLAG from dual; select trunc(to_number(substr((:NEW.DELTIME - :NEW.PMPTIME),1, instr(:NEW.DELTIME - :NEW.PMPTIME,' ')))) * 86400 + to_number(substr((:NEW.DELTIME - :NEW.PMPTIME), instr((:NEW.DELTIME - :NEW.PMPTIME),' ')+1,2)) * 3600 + to_number(substr((:NEW.DELTIME - :NEW.PMPTIME), instr((:NEW.DELTIME - :NEW.PMPTIME),' ')+4,2) ) * 60 + to_number(substr((:NEW.DELTIME - :NEW.PMPTIME), instr((:NEW.DELTIME - :NEW.PMPTIME),' ')+7,2)) + to_number(substr((:NEW.DELTIME - :NEW.PMPTIME), instr((:NEW.DELTIME - :NEW.PMPTIME),' ')+10,6)) / 1000000 into :NEW.DELLAG from dual; select trunc(to_number(substr( (:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT),1, instr(:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT,' ')))) * 86400 + to_number(substr((:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT), instr((:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT),' ')+1,2)) * 3600 + to_number(substr((:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT), instr((:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT),' ')+4,2) ) * 60 + to_number(substr((:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT), instr((:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT),' ')+7,2)) + to_number(substr((:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT), instr((:NEW.TARGET_COMMIT - :NEW.SOURCE_COMMIT),' ')+10,6)) / 1000000 into :NEW.TOTALLAG from dual; end ; / ALTER TRIGGER &&ogg_user..GGS_HEARTBEAT_TRIG_HIST ENABLE;
执行该脚本,或直接修改上面用户执行 sql 都可。
创建好心跳表后,需要在源端对心跳表添加附加日志
GGSCI> ADD TRANDATA OGG112.HEARTBEAT
3. 目标端允许心跳表触发器
当在目标上插入或更新记录时,目标心跳表上的触发器 将 进行计算 , 延迟时间以微秒表示。触发器的配置取决于GoldenGate 的版本。在 12c 之前, NOSUPPRESSTRIGGERS 为缺省值 , 在12c 中, SUPPRESSTRIGGES 是默认的。
如果使用SUPRESSTRIGERS ,则需要排除心跳表触发器,否则会发现由触发器填充的列将为空。从 suppresstrigers 中排除触发器的方法 是在应用进程中添加如下配置:(本次目标端采用 ogg12.1 ,需要该配置)
SQLEXEC "begin dbms_ddl.set_trigger_firing_property('C##OGG112','GGS_HEARTBEAT_TRIG', FALSE);end;"
SQLEXEC "begin dbms_ddl.set_trigger_firing_property('C##OGG112','GGS_HEARTBEAT_TRIG_HIST', FALSE);end;"如果本身目标端没有禁用触发器,则不用管。
如果本身目标端没有禁用触发器,则不用管。
4.源端配置心跳表更新
源端通过job定时调用存储过程的方式来对心跳表进行更新,每分钟执行一次。 源端执行如下sql脚本
SQL> @HB_DBMS_SCHEDULER.sql
具体脚本如下:
-- connect / as sysdba accept ogg_user prompt 'GoldenGate User name:' grant select on v_$instance to &&ogg_user; grant select on v_$database to &&ogg_user; BEGIN SYS.DBMS_SCHEDULER.DROP_JOB(job_name => '&&ogg_user..OGG_HB', defer => false, force => false); END; / CREATE OR REPLACE PROCEDURE &&ogg_user..gg_update_hb_tab IS v_thread_num NUMBER; v_db_unique_name VARCHAR2 (128); BEGIN SELECT db_unique_name INTO v_db_unique_name FROM v$database; UPDATE &&ogg_user..heartbeat SET update_timestamp = SYSTIMESTAMP ,src_db = v_db_unique_name; COMMIT; END; / BEGIN SYS.DBMS_SCHEDULER.CREATE_JOB ( job_name => '&&ogg_user..OGG_HB', job_type => 'STORED_PROCEDURE', job_action => '&&ogg_user..GG_UPDATE_HB_TAB', number_of_arguments => 0, start_date => NULL, repeat_interval => 'FREQ=MINUTELY', end_date => NULL, job_class => '"SYS"."DEFAULT_JOB_CLASS"', enabled => FALSE, auto_drop => FALSE, comments => 'GoldenGate', credential_name => NULL, destination_name => NULL); SYS.DBMS_SCHEDULER.SET_ATTRIBUTE( name => '&&ogg_user..OGG_HB', attribute => 'restartable', value => TRUE); SYS.DBMS_SCHEDULER.SET_ATTRIBUTE( name => '&&ogg_user..OGG_HB', attribute => 'logging_level', value => DBMS_SCHEDULER.LOGGING_OFF); SYS.DBMS_SCHEDULER.enable( name => '&&ogg_user..OGG_HB'); END; /
检查job状态
col REPEAT_INTERVAL format a15
col NEXT_RUN_DATE format a38
col OWNER format a10
col JOB_NAME format a8
set linesize 120
select
owner,
job_name,
job_class,
enabled,
next_run_date,
repeat_interval
from
dba_scheduler_jobs
where
owner = decode(upper('&&ogg_user'), 'ALL', owner, upper('&&ogg_user'));
OWNER JOB_NAME JOB_CLASS ENABL NEXT_RUN_DATE REPEAT_INTERVAL
---------- -------- ------------------------------ ----- -------------------------------------- ---------------
OGG112 OGG_HB DEFAULT_JOB_CLASS TRUE 05-NOV-24 03.28.28.300000 PM PRC FREQ=MINUTELY
5.挖掘进程配置
本次我们通过include文件的方式来配置,也可直接将心跳表的配置写到进程配置中。 在./dirprm目录下创建HB_Extract.inc文件 注意:ogg的配置从12c开始,双引号需要改成单引号。 本次源端为ogg11g,可以使用双引号。
vi ./dirprm/HB_Extract.inc
添加
-- HB_Extract.inc
-- Heartbeat Table
-- update 9-1-12 SGEORGE – no checkpoint info.
TABLE ogg112.HEARTBEAT,
TOKENS (
CAPGROUP = @GETENV ("GGENVIRONMENT", "GROUPNAME"),
CAPTIME = @DATE ("YYYY-MM-DD HH:MI:SS.FFFFFF","JTS",@GETENV ("JULIANTIMESTAMP")),
EDDLDELTASTATS = @GETENV ("DELTASTATS", "DDL"),
EDMLDELTASTATS = @GETENV ("DELTASTATS", "DML")
);
修改挖掘进程
GGSCI (rac1) 3> edit param sm_ext extract sm_ext --setenv (NLS_LANG="SIMPLIFIED CHINESE_CHINA.ZHS16GBK") userid ogg112 password ogg112 TRANLOGOPTIONS INTEGRATEDPARAMS(parallelism 2) LOGALLSUPCOLS UPDATERECORDFORMAT COMPACT exttrail ./dirdat/sm TranlogOptions DBLOGREADER FETCHOPTIONS FETCHPKUPDATECOLS ddl include objname zmy.* exclude objtype 'TRIGGER' DDLOPTIONS ADDTRANDATA RETRYOP RETRYDELAY 10 MAXRETRIES 10 -- This is the Heartbeat table include dirprm/HB_Extract.inc table zmy.t_pricetable;
6.传输进程配置
在传输进程参数文件中,需要包含一个TABLE语句,以便在记录通过传输进程时将传输进程名和当前时间戳添加到记录中。 注意:如果正在进行DDL复制,则需要为使用DDL的表添加PASSTHRU,为心跳表添加NOPASSTHRU。 在./dirprm目录下创建HB_pmp.inc文件
vi ./dirprm/HB_Extract.inc
-- HB_pmp.inc
-- Heartbeat Table
table ogg112.heartbeat,
TOKENS (
PMPGROUP = @GETENV ("GGENVIRONMENT","GROUPNAME"),
PMPTIME = @DATE ("YYYY-MM-DD HH:MI:SS.FFFFFF","JTS",@GETENV
("JULIANTIMESTAMP"))
);
修改传输进程
GGSCI (rac1) 5> edit param sm_dmp extract sm_dmp userid odc111,password odc111 --USERIDALIAS tiger1 rmthost 192.168.242.109, mgrport 7809 --ENCRYPT AES192, KEYNAME securekey2 rmttrail ./dirdat/sm -- Heartbeat include dirprm/HB_pmp.inc passthru table zmy.*;
7.应用进程配置
在./dirprm目录下创建HB_Rep.inc文件 注意:ogg的配置从12c开始,双引号需要改成单引号。 本次目标端为ogg12c,所以需要单引号。
vi ./dirprm/HB_Rep.inc
-- Heartbeat table
MAP ogg112.HEARTBEAT, TARGET c##ogg112.GGS_HEARTBEAT,
KEYCOLS (DELGROUP),
INSERTMISSINGUPDATES,
COLMAP (USEDEFAULTS,
ID = 0,
SOURCE_COMMIT = @GETENV ('GGHEADER', 'COMMITTIMESTAMP'),
EXTRACT_NAME = @TOKEN ('CAPGROUP'),
CAPTIME = @TOKEN ('CAPTIME'),
PMPGROUP = @TOKEN ('PMPGROUP'),
PMPTIME = @TOKEN ('PMPTIME'),
DELGROUP = @GETENV ('GGENVIRONMENT', 'GROUPNAME'),
DELTIME = @DATE ('YYYY-MM-DD HH:MI:SS.FFFFFF','JTS',@GETENV ('JULIANTIMESTAMP')),
EDDLDELTASTATS = @TOKEN ('EDDLDELTASTATS'),
EDMLDELTASTATS = @TOKEN ('EDMLDELTASTATS'),
RDDLDELTASTATS = @GETENV ('DELTASTATS', 'DDL'),
RDMLDELTASTATS = @GETENV ('DELTASTATS', 'DML')
);
MAP ogg112.HEARTBEAT, TARGET c##ogg112.GGS_HEARTBEAT_HISTORY,
KEYCOLS (ID),
INSERTALLRECORDS,
COLMAP (USEDEFAULTS,
ID = 0,
SOURCE_COMMIT = @GETENV ('GGHEADER', 'COMMITTIMESTAMP'),
EXTRACT_NAME = @TOKEN ('CAPGROUP'),
CAPTIME = @TOKEN ('CAPTIME'),
PMPGROUP = @TOKEN ('PMPGROUP'),
PMPTIME = @TOKEN ('PMPTIME'),
DELGROUP = @GETENV ('GGENVIRONMENT', 'GROUPNAME'),
DELTIME = @DATE ('YYYY-MM-DD HH:MI:SS.FFFFFF','JTS',@GETENV ('JULIANTIMESTAMP')),
EDDLDELTASTATS = @TOKEN ('EDDLDELTASTATS'),
EDMLDELTASTATS = @TOKEN ('EDMLDELTASTATS'),
RDDLDELTASTATS = @GETENV ('DELTASTATS', 'DDL'),
RDMLDELTASTATS = @GETENV ('DELTASTATS', 'DML')
);
编辑应用进程 需要允许心跳表的触发器
GGSCI 39> edit param rep1
replicat rep1
--setenv (NLS_LANG="SIMPLIFIED CHINESE_CHINA.ZHS16GBK")
DBOPTIONS INTEGRATEDPARAMS(parallelism 6)
userid c##ogg112@testpdb, password c##ogg112
--handlecollisions
ASSUMETARGETDEFS
--如果源表和目标表没有相同的结构,那么使用SOURCEDEFS参数而不是ASSUMETARGETDEFS。
ALLOWNOOPUPDATES
DBOPTIONS DEFERREFCONST
HANDLETPKUPDATE
--batchsql
ddlerror 955 ignore
ddlerror 1917 ignore
ddlerror 24344 ignore
ddlerror 1031 ignore
ddl include mapped
DISCARDFILE ./dirrpt/sm.dsc, APPEND megabytes 20
DISCARDROLLOVER on sunday
--DISCARDROLLOVER
SQLEXEC "begin dbms_ddl.set_trigger_firing_property('C##OGG112','GGS_HEARTBEAT_TRIG', FALSE);end;"
SQLEXEC "begin dbms_ddl.set_trigger_firing_property('C##OGG112','GGS_HEARTBEAT_TRIG_HIST', FALSE);end;"
include ./dirprm/HB_Rep.inc
map zmy.* target zmy.*;
8.重启进程并检查
各进程配置好后,重启生效。
stop sm_ext start sm_ext stop sm_dmp start sm_dmp stop rep1 start rep1
检查心跳表配置是否成功
源HEARTBEAT 表

可以看到该表只有两列更新。
目标
GGS_
HEARTBEAT
表

可以看到该表只有当前最新一条记录。
目标GGS_HEARTBEAT_HISTORY
表

可以看到该表有所有历史记录,每分钟的记录。
延迟查询
set pagesize 200 col "Total Lag" format a30 col "Extract Lag" format a30 col "Pump Lag" format a30 select DELGROUP, (SOURCE_COMMIT - CAPTIME ) "Extract Lag", (SOURCE_COMMIT - PMPTIME ) "Pump Lag", (SOURCE_COMMIT - TARGET_COMMIT ) "Total Lag" from target.ggs_heartbeat_history order by id;

12.2之前版本的心跳表配置结束。
