前段时间分了一个bug,是core上的bug但是还是得自己改主要是自己心软不好意思推给别人,于是自己就看了下。主要是一个DB 的relplicate 脚本的问题,数据库在同步admin和customer 数据的时候,有几个表的数据没有同步,出错了,错误信息如下:
ERROR: The syncronization of table ARM_PLUGIN_PROCESS_REF is failing: installing data to the remote table. ORA-22804: remote operations not permitted on object tables or user-defined type columns Synchronizing: ARM_PLUGIN_PROCESS_REF from RDCO1108 to ARM_PLUGIN_PROCESS_REF@RDCO1109 ERROR: The syncronization of table ARM_ACTION_PLUGIN_MAP_VALUES is failing: installing data to the remote table. ORA-22804: remote operations not permitted on object tables or user-defined type columns Synchronizing: ARM_ACTION_PLUGIN_MAP_VALUES from RDCO1108 to ARM_ACTION_PLUGIN_MAP_VALUES@RDCO1109 ERROR: The syncronization of table ARM_PLUGIN_PROCESS_VALUES is failing: installing data to the remote table. ORA-22804: remote operations not permitted on object tables or user-defined type columns Synchronizing: ARM_PLUGIN_PROCESS_VALUES from RDCO1108 to ARM_PLUGIN_PROCESS_VALUES@RDCO1109
我自己总结了以下的analysis solution:
When use DB link replicate data from source db to target db. The target db will mistake the xmltype as user-defined type, so in source db push data to target db failed. But if we use the workaround solution that target db pull the data from source db, that would be ok.
So we change the logic from in source_db execute
Insert into table_name@target_db select * from table_name;
to in target_db execute
Insert into table_name select * from table_name@source_db;
很明显就是既然不能我不能push给你,那你就自己拿吧。
接下来的问题来了,要把这个solution加到原来的脚本中,5000多行的脚本啊,哎看了一晚上终于弄明白了大概的逻辑然后找到地方进行了如下的修改:
1.对于要操作的表查看他是不是有xmltype这种类型的列,如果有的话就进入第二步加的逻辑中出来,否则的话就做原来的逻辑
do if [[ $(echo $line | egrep -ic 'rowsselected' | awk '{print $1}') = 0 ]] then tblName=$(echo $line | cut -f1 -d'|') dsdatabase=$(echo $line | cut -f2 -d'|') cat 1>$QUERY_FILE <<EOF select count(1) from user_tables where table_name = '$tblName'; exit; EOF ExecSql $dsdatabase sed 's/ //g' $QUERY_RESULT | sed '/^COUNT/d' | sed '/^--*/d' | sed '/^$/d' > a.$$.tmp mv a.$$.tmp $QUERY_RESULT if [[ $(cat $QUERY_RESULT | awk '{print $1}') -gt 0 ]] then <span style="color:#333333;"> </span><strong><span style="color:#ff6666;">#CBS00166931 begin (for the table which has data_type = 'XMLTYPE',this CBS don't support #remote DB table has constraint_type = 'R' ,constraint_type = 'P',trigger_name not like 'RT_%') cat 1>$QUERY_FILE <<EOF select COUNT(1) from USER_TAB_COLUMNS where table_name='$tblName' and data_type='XMLTYPE' ; exit; EOF ExecSql $dsdatabase sed 's/ //g' $QUERY_RESULT | sed '/^COUNT/d' | sed '/^--*/d' | sed '/^$/d' > a.$$.tmp mv a.$$.tmp $QUERY_RESULT if [[ $(cat $QUERY_RESULT | awk '{print $1}') -gt 0 ]] then </span><span style="color:#3366ff;">SyncTables_xmltype</span><span style="color:#ff6666;"> $tblName $WORK_DB $dsdatabase continue fi #CBS00166931 end</span></strong> cat 1>$QUERY_FILE <<EOF set serveroutput on; set linesize 1000; alter session set remote_dependencies_mode=signature; delete from rt_tmp_out_msgs where server = '$dsdatabase'; commit; begin dbms_output.enable(NULL); -- Call the procedure Replicate.SyncTables('$tblName', '$dsdatabase'); end; / set head off; set feed off; select msg from rt_tmp_out_msgs where server = '$dsdatabase' order by server,instime; exit; EOF ExecSql $WORK_DB if [[ $(cat $QUERY_RESULT | grep -vi synchronizing | grep -vi $tblName | egrep -ci Error) > 0 ]] then UserInfo INFORM_SCREEN "*** WARNING *** Replication errors in the log. Please review." 1 1 1 fi if [[ $(cat $QUERY_RESULT | grep -v "*** WARNING ***" | grep -vi $tblName | egrep -ci warning) > 0 ]] then UserInfo INFORM_SCREEN "*** WARNING *** Replication problems in the log. Please review." 1 1 1 fi print -u9 "" sed '/ procedure successfully/d' $QUERY_RESULT | sed '/Session altered/d' | sed '/^$/d' | sed '/deleted./d' | sed '/complete./d'>${QUERY_RESULT}.tmp cat ${QUERY_RESULT}.tmp >&9 2>/dev/null rm ${QUERY_RESULT}.tmp else UserInfo INFORM "Table $tblName does not exist in $dsdatabase" 1 2 1 fi fi done
2.这步就是新增加的专门处理有xmltype这种类型的表逻辑,新增加了一个函数。
function SyncTables_xmltype { tblName=$1 srcdb=$2 tardb=$3 cat 1>$QUERY_FILE <<EOF delete from $tblName; exit; EOF ExecSql $tardb if [[ $(egrep -c -i 'ORA|errors:|fail|error|Msg' $QUERY_RESULT) -gt 0 ]] then print -u9 "" cat $QUERY_RESULT >&9 FatalError "delete $tblName from $tardb error" fi cat 1>$QUERY_FILE <<EOF Insert into $tblName select * from $tblName@$srcdb; exit; EOF ExecSql $tardb if [[ $(egrep -c -i 'ORA|errors:|fail|error|Msg' $QUERY_RESULT) -gt 0 ]] then print -u9 "" cat $QUERY_RESULT >&9 FatalError "insert $tblName from $srcdb to $tardb error" fi cat 1>$QUERY_FILE <<EOF select COUNT(1) from $tblName; exit; EOF ExecSql $srcdb sed 's/ //g' $QUERY_RESULT | sed '/^COUNT/d' | sed '/^--*/d' | sed '/^$/d' > a.$$.tmp mv a.$$.tmp $QUERY_RESULT srcCount=$(cat $QUERY_RESULT | awk '{print $1}') cat 1>$QUERY_FILE <<EOF select COUNT(1) from $tblName; exit; EOF ExecSql $tardb sed 's/ //g' $QUERY_RESULT | sed '/^COUNT/d' | sed '/^--*/d' | sed '/^$/d' > a.$$.tmp mv a.$$.tmp $QUERY_RESULT tarCount=$(cat $QUERY_RESULT | awk '{print $1}') if [[ $srcCount != $tarCount ]] then echo "ERROR: Post synch record counts for table $tblName and remote table $tblName@$tardb do not match" >&9 fi echo " " >&9 echo "Synchronizing: $tblName from $srcdb to $tblName@$tardb" >&9 echo "Source row count: $tblName@$srcdb: $srcCount" >&9 echo "Target row count: $tblName@$tardb: $tarCount" >&9 echo "------------------------------------------------------------" >&9 }