首页 > 数据库 > Oracle > OGG数据库迁移方案(四)
监控
源库
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.8
2. 停止replicat 进程
cd $GG_HOME
ggsci
GGSCI> stop r_tbcs
3. 检查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/r1
4. 修改新建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_1
6. 删除旧的replicat 进程
GGSCI>dblogin userid ggadmin,password ***
GGSCI>delete r_tbcs
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/10201716/viewspace-2939530/ ,如需转载,请注明出处,否则将追究法律责任。