oracle迁移完成后对比数据一致性用法

对比数据一致性用法

1, 在目标端和生产端分别创建如下Procedure

create or replace function f_getResultHash(
p_owner varchar2, –表owner
p_table_name varchar2, –表名
p_part_name varchar2, –分区名,对于分库主库对比,必须加这个
p_date_str varchar2 default null, –由于对比时不能保证同时进行,尽可能由外面传入这个参数。如果数据基本静止,可以不加这个参数
p_date_col varchar2 default null, –如果不传这个参数,默认会使用as of timestamp查询,对于OGG这种持续同步的环境,由于存在一定延时,可能会有误差。尽可能指定时间字段列,可以避免,如transaction time
p_column_list varchar2 default null,–根据需要,可以只对比特定列,以逗号分隔,前后不能加空格
p_hash_size number default power(2,31)
–由于采用加和方式对比结果集,如果对比记录数太大,有可能会超出Oracle数字最大值,必要时可以减少这个值来避免,正常情况下不传参即可
) return varchar2 as
v_sql_text clob;
v_date_str varchar2(24);
v_res varchar2(4000);
v_col_len number default 0;
v_max_col_len number default 3800;
begin
v_sql_text :=’select ‘’rowCount:’’||count(*)||’;
for collist in (
–获取栏位列表,由于ora_hash不支持LOB/LONG字段,需要移除,另外,也同时把过滤column_list的判断放在这里
select rownum as r,column_name,data_length from all_tab_columns
where table_name = p_table_name and owner = p_owner
–此处过滤LOB/LONG字段
and data_type not in (‘CLOB’,’BLOB’,’LONG’,’LONGRAW’)
and ( p_column_list is null or
–此处过滤column_list
instr(‘,’||upper(p_column_list)||’,’,column_name)>0 )
) loop
if(collist.r=1) then
–第一个,以ora_hash(column_name开始
v_sql_text :=v_sql_text ||’ ‘’,ColHash:’’||sum(ora_hash( ‘||collist.column_name||’||’’#’’’;
v_col_len := collist.data_length+1;
else
–ora_hash参数不能超出一定长度,超出则新起一个ora_hash
if (v_col_len+collist.data_length+1)>v_max_col_len then
v_sql_text :=v_sql_text ||’,’|| p_hash_size ||’)) ||’’#’’||sum(ora_hash(‘||collist.column_name||’||’’#’’’;
v_col_len:=collist.data_length+1;
–正常叠加后面的字段
else
v_sql_text :=v_sql_text ||’||’||chr(10)||collist.column_name||’||’’#’’’;
v_col_len:=v_col_len+collist.data_length+1;
end if;
end if;
end loop;
–ora_hash增加p_hash_size,必要时可以降低hash_size,避免sum出来的值过大,超过PLSQL最大数字。
v_sql_text := v_sql_text ||’,’|| p_hash_size ||’))
from ‘||p_owner||’.’||p_table_name;
–增加分区支持,主要用于主库分库判断
if (p_part_name is not null) then
v_sql_text:= v_sql_text||’ partition (‘||p_part_name||’)’;
end if;
–时间戳
if(p_date_str is null) then
select nvl(p_date_str,to_char(sysdate,’yyyymmddhh24miss’)) into v_date_str from dual ;
end if;
–对于OGG,由于存在一定延时,可能会有误差。尽可能指定时间字段列,可以避免,如transaction time
if(p_date_col is null ) then
v_sql_text :=v_sql_text||’
as of timestamp to_date(:d,’’yyyymmdd-hh24miss’’)’;
else
v_sql_text :=v_sql_text||’
where ‘||p_date_col ||’ <= to_date(:d,’’yyyymmdd-hh24miss’’)’;
end if;
–万一运行出错,可以把语句打印出来,测试运行的SQL
–dbms_output.put_line(v_sql_text||’ ‘||v_date_str);
execute immediate v_sql_text into v_res using v_date_str;
return v_res;
end;
/

2, 程序中(比如SHELL) 获取当前时间,格式为 yyyymmdd-hh24miss

3, 分别连接两个库,执行以下代码,由于分库和汇集库表分区本来就不一样,所以需要输入分区
select f_getResultHash(‘<表用户>’,’表名’,’<分区名>’,’<时间>’,’<时间列>’) from dual;

4, 对比出来的结果,如果一致,证明数据同步正确。

5, 根据情况,也可以只对比特定列功能
select f_getResultHash(‘<表用户>’,’表名’,’<分区名>’,’<时间>’,’<时间列>’,’以逗号分隔列的列表’) from dual;