[置顶] dblink 同步表数据时对于类型是XMLTYPE的表出错

前段时间分了一个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

去看了看这三个表有什么特别处,发现这三个表都是带有XMLTYPE这种特殊的数据类型,所以又可能跟这个有关。去网上查了一些资料,终于在stackoverflow上找到了解决问题的方法,stackoverflow真是强大啊。附上地址: 点击打开链接


我自己总结了以下的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
}

改了这个bug后感觉良好,了解了一下shell脚本和duplicate这个脚本的流程,还算有收获吧。









你可能感兴趣的:(linux,shell,DB)