对比数据一致性用法
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;
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。