监控
源库
3 个进程:mgr, ext1, dp1
ps -ef | grep mgr | grep oracle | grep -v grep ps -ef | grep ext1 | grep -v grep ps -ef | grep dp1 | grep -v grep
新营业库
3 个进程:mgr, rep1,rep2
ps -ef | grep mgr | grep oracle | grep -v grep
ps -ef | grep rep1 | grep -v grep
ps -ef | grep rep2 | grep -v grep
将以上进程的监控放在监控程序里,若进程异常及时报警。 层面,使用ggsci 命令监控 执行info all 查看各进程运行情况,命令输出说明如下:
Group 表示进程的名称(MGR 进程不显示名字);Lag 表示进程的延时;Status 表示进程的状态。有四种状态:
STARTING: 表示正在启动过程中 RUNNING :表示进程正常运行 STOPPED :表示进程被正常关闭 ABENDED :表示进程非正常关闭,需要进一步调查原因
正常情况下,所有进程的状态应该为RUNNING ,且Lag 应该在10 分钟以内。
l 监控进程状态,若发现状态为‘ABENDED ’,及时告警。
l 监控lag 信息,‘Lag at Chkpt ’的值大于某一个值(比如1 小时,阀值可以调整)时告警。
l 监控checkpoint 信息,‘Time Since Chkpt ’值过大表示当前执行的sql 较慢,可以设置一个阀值(比如30 分钟),超过阀值告警。
ggserr.log 在ggserr.log 中可以查看到的内容如下:
GGSCI 命令的历史记录。
GoldenGate 进程的启动与停止。
已执行的处理。
发生的错误。
信息和警告消息Ggserr.log 位置:$GG_HOME 。
l 监控‘ABENDED ’、‘ ERROR ’、‘ORA- ’关键字。
在源库上的应用不停止的情况下,为判断GoldenGate 是否将源库的更新都复制到了目标端,一种可实施的做法是: n 将表分为三部分:静态表,小表和大表。通过数据库链接,执行select minus 语句执行对比。静态表只需比对一次,对小表进行全量对比,大表根据时间或按分区对比历史数据,即对比今天零点之前的数据(假定零点之后不再更新)。 n 应用方面从业务角度对数据进行校验。 割接时在停止了应用后,源与目标端的数据应该为静止的。此时将数据分为三类: n 大的分区表 n 关键业务表 n 非分区表 分区表通过比较各个分区的数据rowcount 和number 类型字段的数据和,对于使用时间分区的数据,历史分区中的数据理论上基本不再发生变化,历史分区的数据rowcount 相等即可认定数据一致。对于使用数字分区的分区表,历史分区的数据还可能被修改的情况,对于最核心的表再加一个比对number 字段的sum 的过程。另外由于Goldengate 的同步也有一致性的检查,Goldengate 通过中没有发生大量update 的冲突,即可认为这些历史分区的数据也是一致的。 比对分区的rowcount 的脚本,该脚本需在源库和目标库上都执行,源库的数据插入到system.source_table_count 中,目标库的数据插入到system.target_table_count 中,以下对比sum 的步骤类似:
getcount.sql:
select 'insert into system.target_table_count select /*+ full(t) parallel (16) */''' || table_name ||
''' table_name , ''' || partition_name ||
''' partition_name ,count(*) from 复制用户名称.' || table_name ||
' partition(' || partition_name || ') t;'
from dba_tab_partitions
where table_owner = ' 复制用户名称'
and table_name in (select distinct table_name
from system.ggrep_table
where partationed = 'YES')
order by table_name, partition_name;
到/oracle/tmp目录下: sqlplus '/as sysdba' set linesize 300 set pagesize 0 set heading off spool count.sql @getcount.sql spool off
请先去掉第一行和最后几行,然后进行切分
sed -n '1,20000p' count.sql >count_1.sql sed -n '20001,40000p' count.sql >count_2.sql sed -n '40001,60000p' count.sql >count_3.sql sed -n '60001,80000p' count.sql >count_4.sql sed -n '80001,100000p' count.sql >count_5.sq1 sed -n '100001,120000p' count.sql >count_5.sq1
count_1.sh :
sqlplus '/as sysdba' <<!
set time on
@/oracle/tmp/count_1.sql
commit;
set time off
exit
!
count_2.sh :
sqlplus '/as sysdba' <<!
set time on
@/oracle/tmp/count_2.sql
commit;
set time off
exit
!
count_3.sh :
sqlplus '/as sysdba' <<!
set time on
commit;
@/oracle/tmp/count_3.sql
set time off
exit
!
count_4.sh :
sqlplus '/as sysdba' <<!
set time on
@/oracle/tmp/count_4.sql
commit;
set time off
exit
!
count_5.sh :
sqlplus '/as sysdba' <<!
set time on
@/oracle/tmp/count_5.sql
commit;
set time off
exit
!
count_6.sh :
sqlplus '/as sysdba' <<!
set time on
@/oracle/tmp/count_6.sql
commit;
set time off
exit
!
nohup /oracle/tmp/count_1.sh >/oracle/tmp/count_1.log & nohup /oracle/tmp/count_2.sh >/oracle/tmp/count_2.log & nohup /oracle/tmp/count_3.sh >/oracle/tmp/count_3.log & nohup /oracle/tmp/count_4.sh >/oracle/tmp/count_4.log & nohup /oracle/tmp/count_5.sh >/oracle/tmp/count_5.log & nohup /oracle/tmp/count_6.sh >/oracle/tmp/count_6.log &number 字段的sum 的脚本:
getsum.sql
select 'insert into system.target_table_sum select /*+ full(t) parallel (16) */''' || table_name ||
''' table_name ,' || '''' || column_name ||
''' column_name,to_char(sum(' || column_name || ')) SUM from 复制用户名称.' || table_name ||' t;'
from dba_tab_columns a
where a.owner = ' 复制用户名称'
and a.table_name in ('ACCOUNT','ACCOUNT_PRIVILEGE','ACCOUNT_RATEPLAN',
'ACC_SETTLE_TYPE','CS_CU_SUBSEXTATTR','CUSTOMER',
'GROUP_ACCOUNT','GROUP_CUSTOMER','PERSON_CUSTOMER',
'RECEPTION','SUBSCRIBER','SUBS_APPDSTATUS','SUBS_BILLMAIL',
'SUBS_CUSTRELATION','SUBS_DEPOSIT','SUBS_FORBID','SUBS_IMEI',
'SUBS_PAYPLAN','SUBS_PRESENT_DATA','SUBS_PRESENT_DUMMY','SUBS_PRESENT_REAL',
'SUBS_PRIVATTR','SUBS_PRIVILEGE','SUBS_PRODUCT','SUBS_RATEPLAN', 'SUBS_RELATION','SUBS_RESOURCE','SUBS_REWARD_LOG_ATTR','SUBS_REWARD_LOG',
'SUBS_SERVICEATTR','SUBS_SERVICE','SUBS_SPSERVICEATTR','SUBS_SPSERVICE',
'USER_PASSWORD_LOG','RECEPTION')
and a.DATA_TYPE='NUMBER'
order by table_name, column_name;
到/oracle/tmp目录下: sqlplus '/as sysdba' set linesize 300 set pagesize 0 set heading off spool sum.sql @getsum.sql spool off
sum.sh
sqlplus '/as sysdba' <<!
set time on
@/oracle/tmp/sum.sql
commit;
set time off
exit
!
nohup /oracle/tmp/sum.sh >/oracle/tmp/sum.log & 通过一个连接到源库上的dblink :yy3a 对比rowcount 和sum 的结果,得到结果之后对比compare_table_count 和compare_table_sum 的第三、第四列数据是否都一致。
目标库上执行:
create table compare_table_count as
select a.table_name,
a.partition_name,
a.count source_count,
b.count target_count
from system.target_table_count a, system.source_table_count@yy3a b
where a.table_name = b.table_name
and a.partition_name = b.partition_name;
create table compare_table_sum as
select a.table_name,
a.column_name,
a.sum source_sum,
b.sum target_sum
from system.target_table_sum a, system.source_table_sum@yy3a b
where a.table_name = b.table_name
and a.column_name = b.column_name; 非分区表直接通过源和目标的相应表minus 得到结果,为了准确该minus 需要取双向的结果。脚本如下:
target-source.sql
select 'select * from 复制用户名称.' || table_name ||
' a minus select * from 复制用户名称.' || table_name || '@to_source b;'
from ggrep_table
where partitioned = 'NO';
souce-target.sql
select 'select * from 复制用户名称.@to_target ' || table_name ||
' a minus select * from 复制用户名称.' || table_name || 'b;'
from ggrep_table
where partitioned = 'NO';
在/oracle/tmp目录下执行:
sqlplus '/as sysdba'
set linesize 300
set pagesize 0
set heading off
spool st_compare.sql
@/oracle/tmp/source-target.sql
spool off
spool ts_compare.sql
@/oracle/tmp/target-source.sql
spool off
应用人员停应用; 确认数据库没有应用用户连接,并将应用用户锁定 。
col username for a10
col program for a30
col machine for a10
col sql_id for a15
col event for a30
select username,count(*) from gv$session group by username;
alter user xxx account lock; 的extract 、pump 进程 向源端数据库测试表中插入验证数据
insert into xxx.ogg_test values(1,sysdate);
commit; 到新系统查询数据是否同步成功
在新系统数据库查询
select * from xxx.test; 若确认数据同步完成,停止extract 和pump 进程
stop ext1
stop dp1 的replicat 进程
stop rep1 在 操作 执行下面的SQL ,生成用于 用外键约束的脚本文件:
set echo off verify off trim on heading off feedback off
set pagesize 2000 linesize 150
spool enable_foreign_constraints.sql
select 'alter table '||owner||'.'||table_name|| ' enable constraint '||constraint_name||';'
from dba_constraints
where constraint_type = 'R' and owner in('PRDABPPVMI1','PRDSPUSERVMI1');
spool off 在新数据库执行enable_foreign_constraints.sql 脚本启用外键约束。 然后执行以下语句确认所有的外键约束都已经启用:
Col owner for a10
Col table_name for a30
Col constraint_name for a30
select owner, table_name, constraint_name, status
from dba_constraints
where constraint_type='R' and owner in('PRDABPPVMI1','PRDSPUSERVMI1'); 执行下面的SQL ,生成用于启用级联删除的脚本文件:
set echo off verify off trim on heading off feedback off
set pagesize 2000 linesize 150
spool ensable_cascade_delete_constraints.sql
select 'alter table '||owner||'.'||table_name||' enable constraint '||constraint_name||';'
from dba_constraints
where owner in('PRDABPPVMI1','PRDSPUSERVMI1') and constraint_type = 'R' and delete_rule = 'CASCADE';
spool off 在新数据库执行enable_cascade_delete_constraints.sql 脚本禁用级联删除。 然后执行以下语句确认所有的级联删除都已经禁用:
select owner, table_name, constraint_name, status
from dba_constraints
where delete_rule = 'CASCADE'and owner in('PRDABPPVMI1','PRDSPUSERVMI1'); 使用以下命令将新数据库的job 队列修改为 1000 (默认值,可根据具体情况设置) ,从而达到启用目标库job 的目的:
alter system set job_queue_processes =1000 scope = both sid = '*'; 修改为以后使用以下命令确认当前的修改已经生效,job 队列为1000 :
show parameter job; 执行下面的语句,生成启用触发器的脚本文件enable_triggers.sql :
set echo off verify off trim on heading off feedback off
set pagesize 2000 linesize 150
spool enable_triggers.sql
select 'alter trigger '||owner||'.'||trigger_name|| ' enable;'
from dba_triggers
where owner in('PRDABPPVMI1','PRDSPUSERVMI1');
spool off 执行脚本enable_triggers.sql 启用触发器。然后执行以下语句确认所有的触发器都已经被启用:
sqlplus / as sysdba
@ enable_triggers.sql
select owner, trigger_name, status
from dba_triggers
where owner in('PRDABPPVMI1','PRDSPUSERVMI1') 由于数据库上sequence 较多,建议用数据泵将源库上的sequence 导入到新库 建议用数据泵将源库上的物化视图导入到新库
慢排查方法 查看进程延迟信息
GGSCI (db1) 8> info all
Program Status Group Lag at Chkpt Time Since Chkpt
MANAGER RUNNING
REPLICAT RUNNING R_TBCS 18:20:00 00:10:07
REPLICAT RUNNING R_TBCS2 00:00:00 00:00:00 ‘Lag at Chkpt ’较大说明进程延迟较大,数据还没追平,可以考虑拆分进程 ‘Time Since Chkpt ’较大说明replicat 进程正在执行的sql 比较慢,可以通过以下方法排查
1. 查找当前复制进程的pid
ps -ef | grep r_tbcs
2. 根据r_tbcs 的进程号找到连接数据库进程的pid
ps -ef | grep <r_tbcs pid>
3. 根据连接数据库进程的pid 找到数据库中session 的sid
4. 查找数据库session 正在执行的sql , 分析sql 的执行计划看是否可以优化(例如:添加索引,更新统计信息等)。 replicat 进程的方法1. 添加新的replicate 进程和配置文件 略,具体步骤参考3.8.82. 停止replicat 进程
cd $GG_HOME
ggsci
GGSCI> stop r_tbcs3. 检查replicat 进程的checkpoint 信息
GGSCI>info r_tbcs, showch
-- 记录下Current Checkpoint信息中的sequence和RBA值。
Current Checkpoint (position of last record read in the data source):
Sequence #: 2157
RBA: 2856752
Timestamp: 2014-09-03 08:13:58.035316
Extract Trail: /oracle/goldengate/ggs/dirdat/r14. 修改新建replicat 进程的read checkpoint 信息 根据step 3 中得到的Current checkpoint 信息修改新建replicat 进程的checkpoint 信息,之后新建的replicat 进程就会从旧replicat 进程停止的位置开始抓取新的信息
GGSCI> alter r_tbcs_0, extseqno <sequence>, extrba <RBA>
GGSCI> alter r_tbcs_1,, extseqno <sequence>, extrba <RBA>5. 启动新建的replicat 进程
GGSCI>start r_tbcs_0
GGSCI>start r_tbcs_16. 删除旧的replicat 进程
GGSCI>dblogin userid ggadmin,password ***
GGSCI>delete r_tbcs
