暂无图片
暂无图片
35
暂无图片
暂无图片
暂无图片

罗海雄:Oracle数据库迁移后数据对比脚本

原创 罗海雄 2021-08-17
9563

对比数据一致性用法

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

评论