1. 程式人生 > >oracle資料庫同步,100萬資料秒級插入

oracle資料庫同步,100萬資料秒級插入

近期為了滿足客戶的(××電網公司)需求,先說下他們的需求,需求如下:

1.實現Ⅱ區、Ⅲ區資料庫的同步,其中Ⅱ區是主資料庫,Ⅲ區是需要同步的資料庫。

2.兩臺資料庫伺服器之間是不能直接通訊的,因為Ⅱ、Ⅲ區之間安裝了隔離裝置,只能通過埠訪問。

3.同步需要保證實時性,資料都是秒級的,一分鐘下來至少是2萬條資料。

看到這個需求我的第一反應估計跟大家是一樣的,就是建立外連線,然後使用merger函式去定時同步,效果是最好的,但最終只能想想了,因為兩臺伺服器根本不能通訊的。

上面的方法行不通了就得換一種方式了,後面經過和同事們討論定下了一個方案,思路如下:

1.使用儲存過程生成更新的或者插入的SQL語句,儲存到表中;

2.使用後臺服務定期讀取表中已經生成好的SQL語句做成bat檔案並壓縮打包;

3.使用傳輸服務將Ⅱ區的檔案傳輸到Ⅲ區指定伺服器並解壓到指定的目錄;

4.使用Ⅲ區的同步服務呼叫bat檔案進行資料插入

思路是沒問題的,基本功能都實現了,但是問題就處在效率提不上去,同步2萬資料需要一分鐘以上,這顯然是不符合需求的。

行不通就只能換一個方案了,不使用批處理來同步了,先程式碼來實現同步;

詳細思路如下:

1.同樣是使用儲存過程生成指定格式的字串(XML格式)儲存到資料庫中,程式碼如下:

1)既然是指定格式的話,肯定要模版才行,下面的程式碼是根據配置生成指定格式的模版

create or replace procedure P_pub_SyncData_InitTemplate is
  /*
   過程名稱:P_pub_SyncData_InitTemplate
   用途:資料庫同步,生成模版
   建立日期:2013-07-03 16:41:00
  */
  V_INSERT_TEMPLATE     VARCHAR2(2000);
  V_INSERT_TEMPLATE_COL VARCHAR2(1000);
  V_INSERT_TEMPLATE_VAL VARCHAR2(1000);
  V_DELETE_TEMPLATE     VARCHAR2(1000);
  V_DATA_XMLTEMPLATE    VARCHAR2(2000);
  V_DATA_TYPETEMPLATE   VARCHAR2(2000);
  V_DELETE_COND_TEMPLATE VARCHAR2(500);
  V_COL_LIST                                                    dbms_sql.Varchar2_Table;                     --欄位集合
  V_COL_TYPE_LIST                                               dbms_sql.Varchar2_Table;                     --欄位型別集合
  CURSOR C_SYNC_CFG IS
    SELECT upper(TABLE_NAME) TABLE_NAME,
           upper(DELETE_CONDITION) DELETE_CONDITION,
           upper(COMPARE_DATE_COL) COMPARE_DATE_COL ,
           EXEC_TYPE,
           SYNCTIME_TYPE,
           TIMETAG_TYPE
      FROM TB_PUB_SYNC_DATA_CFG_NEW;
begin
  FOR V_SYNC IN C_SYNC_CFG LOOP
    SELECT COLUMN_NAME,DATA_TYPE bulk collect into V_COL_LIST,V_COL_TYPE_LIST from USER_TAB_COLUMNS where table_name=V_SYNC.TABLE_NAME;
     --資料插入 欄位
     V_INSERT_TEMPLATE_COL := 'INSERT INTO '|| V_SYNC.TABLE_NAME||'(';
     --資料插入  值
     V_INSERT_TEMPLATE_VAL := ' VALUES(';
     --如果是 是先清空表中的資料  使用truncate  提高效率
     IF V_SYNC.EXEC_TYPE=1 THEN
       V_DELETE_TEMPLATE :='TRUNCATE TABLE '||V_SYNC.TABLE_NAME;
     ELSE
       --刪除模版
       V_DELETE_TEMPLATE     :='DELETE '||V_SYNC.TABLE_NAME||' WHERE 1=1 ';
     END IF;
     --XML中的資料行模版
     V_DATA_XMLTEMPLATE    :='SELECT ''<'||V_SYNC.TABLE_NAME||'DataRow ';
     --表格 列的資料型別模版
     V_DATA_TYPETEMPLATE   :='<'||V_SYNC.TABLE_NAME||'Coltype';
     --資料刪除時  條件列模版
     V_DELETE_COND_TEMPLATE:='<'||V_SYNC.TABLE_NAME||'DelCol DeleteCol="'||V_SYNC.DELETE_CONDITION||'"></'||V_SYNC.TABLE_NAME||'DelCol>';
     FOR  I IN 1..V_COL_LIST.COUNT LOOP
       V_INSERT_TEMPLATE_COL :=V_INSERT_TEMPLATE_COL||V_COL_LIST(I)||',';
       V_INSERT_TEMPLATE_VAL :=V_INSERT_TEMPLATE_VAL||':'||V_COL_LIST(I)||',';
       V_DATA_TYPETEMPLATE   :=V_DATA_TYPETEMPLATE||' '||V_COL_LIST(I)||'="'||initcap(V_COL_TYPE_LIST(I))||'"';
       V_DATA_XMLTEMPLATE    :=V_DATA_XMLTEMPLATE ||' '||V_COL_LIST(I)||'="'||FUN_PUB_SYNC_TEMPLATE_FORMAT(V_COL_LIST(I),V_COL_TYPE_LIST(I))||'"';
      IF V_SYNC.EXEC_TYPE=0 AND INSTR(V_SYNC.DELETE_CONDITION,V_COL_LIST(I))>0 THEN
       V_DELETE_TEMPLATE     :=V_DELETE_TEMPLATE||' AND '||V_COL_LIST(I)||'=:'||V_COL_LIST(I);
      END IF;
     END LOOP;
     V_INSERT_TEMPLATE :=substr(V_INSERT_TEMPLATE_COL,0,length(V_INSERT_TEMPLATE_COL)-1)||') '||substr(V_INSERT_TEMPLATE_VAL,0,length(V_INSERT_TEMPLATE_VAL)-1)||')';
     V_DATA_TYPETEMPLATE :=V_DATA_TYPETEMPLATE||'></'||V_SYNC.TABLE_NAME||'Coltype>';
     V_DATA_XMLTEMPLATE  :=V_DATA_XMLTEMPLATE||'></'||V_SYNC.TABLE_NAME||'DataRow>'' FROM '||V_SYNC.TABLE_NAME||' WHERE 1=1';

  --生成查詢條件模版
  --不區分機組
  IF V_SYNC.TIMETAG_TYPE=1 AND V_SYNC.COMPARE_DATE_COL IS NOT NULL then
    V_DATA_XMLTEMPLATE := V_DATA_XMLTEMPLATE||' AND '||V_SYNC.COMPARE_DATE_COL|| '>{BEGIN_DATE} AND '||V_SYNC.COMPARE_DATE_COL||'<={END_DATE}';
  --區分機組
  ELSIF V_SYNC.TIMETAG_TYPE=0 AND V_SYNC.COMPARE_DATE_COL IS NOT NULL THEN
   V_DATA_XMLTEMPLATE := V_DATA_XMLTEMPLATE||' AND '||V_SYNC.COMPARE_DATE_COL|| '>{BEGIN_DATE} AND '||V_SYNC.COMPARE_DATE_COL||'<={END_DATE} AND SET_CODE={SET_CODE} AND FACTORY_CODE={FACTORY_CODE}';
  ELSIF V_SYNC.TIMETAG_TYPE=0 THEN
   V_DATA_XMLTEMPLATE := V_DATA_XMLTEMPLATE||' AND SET_CODE={SET_CODE} AND FACTORY_CODE={FACTORY_CODE}';
  END IF;
  UPDATE TB_PUB_SYNC_DATA_CFG_NEW SET insert_template=V_INSERT_TEMPLATE,delete_template=V_DELETE_TEMPLATE,DATA_XMLTEMPLATE=V_DATA_XMLTEMPLATE,DELETE_COND_TEMPLATE=V_DELETE_TEMPLATE,DATA_TYPE_TEMPLATE=V_DATA_TYPETEMPLATE WHERE UPPER(TABLE_NAME)=V_SYNC.TABLE_NAME;
  END LOOP;
 
  --插入資料更新狀態標籤
   MERGE INTO TB_PUB_SYNC_TIMESEG_TAG T USING (select 'SYNCSTATUSTAG' TABLE_NAME FROM DUAL) T1 ON (T.TABLE_NAME=T1.TABLE_NAME)
   WHEN NOT MATCHED THEN
   INSERT VALUES('SYNCSTATUSTAG','0','0',SYSDATE,SYSDATE,SYSDATE); 
  
   COMMIT;
   EXCEPTION WHEN OTHERS THEN
   dbms_output.put_line(substr(sqlerrm,0,200));
   rollback;
end P_pub_SyncData_InitTemplate;

2)根據生成的模版去生成資料,程式碼如下:

create or replace procedure P_PUB_JOB_DATA_SYNC_New
/*
 過程名稱:P_JOB_PUB_DATA_SYNC
 用途:資料庫同步,生成資料指令碼
 建立人:顏顯斌
 建立日期:2013-07-03 16:41:00
*/
 is                                                       
  TYPE                       Mycursor_Type is ref cursor;                                     --遊標型別變數
  CUR_SQL                    Mycursor_Type;                                                   --遊標變數
  V_SQL                      VARCHAR2(2000);
  V_SYNC_TIME                date;
  V_FACTORY_CODE_LIST        dbms_sql.Varchar2_Table;
  V_SET_CODE_LIST            dbms_sql.Varchar2_Table;
  V_BEGIN_DATE               DATE;
  V_END_DATE                 DATE;
  V_TEMP_SQL                 VARCHAR2(2000);
  v_orderno                  integer:=0;                                        --記錄行數
  v_count                    integer;
  v_xmltemp                  varchar2(2000);
  v_exectype                 varchar2(30);
  v_commsql                  varchar2(200);
  CURSOR C_DataSyncCfg IS
  SELECT upper(TABLE_NAME) TABLE_NAME,
           upper(DELETE_CONDITION) DELETE_CONDITION,
           upper(COMPARE_DATE_COL) COMPARE_DATE_COL ,
           insert_template,
           delete_template,
           data_xmltemplate,
           delete_cond_template,
           data_type_template,
           sync_type,
           IS_SYNC,
           EXEC_TYPE,
           SYNCTIME_TYPE,
           TIMETAG_TYPE,
           order_no
      FROM TB_PUB_SYNC_DATA_CFG_NEW where is_sync=1;

 begin
   --為了保證Xml的完整性,當表中還有資料的時候不再插入,等待後臺服務讀取完成再進行寫入
   select count(0) into v_count from tb_pub_sync_data_sql;
   if v_count>0 then
     return;
   end if;
   --更新同步資料的狀態標籤,0:正在生成資料;1:資料生成完成後臺可以呼叫(目的:保證XML檔案的完整性)
   execute immediate 'update TB_PUB_SYNC_TIMESEG_TAG set factory_code=0,set_code=0,begin_time=sysdate,end_time=sysdate,update_time=sysdate where table_name=''SYNCSTATUSTAG''';
   --使用繫結變數  公用的插入資料SQL
   v_commsql :='INSERT INTO TB_PUB_SYNC_DATA_SQL (table_name, SQL_CONTENT, UDPATE_TIME,ORDER_NO)  VALUES (:x,:x,:x,:x)';
   --插入Xml頭和根節點
   execute immediate v_commsql using '','<?xml version="1.0" encoding="utf-8" ?><XMLROOT>',sysdate,v_orderno;
   v_orderno :=v_orderno+1;
   --得到配置表中的資訊
   for V_DataSyncCfg in C_DataSyncCfg
   LOOP
     --拼湊程式處理中需要的  執行型別
     if V_DataSyncCfg.EXEC_TYPE=1 then
       v_exectype := 'TruncateAndInsert';
     elsif V_DataSyncCfg.EXEC_TYPE=0 then
       v_exectype := 'DeleteAndInsert';
     elsif V_DataSyncCfg.EXEC_TYPE=2 then
       v_exectype := 'Insert';
     else
       v_exectype := 'DeleteAndInsert';
     end if;
     --插入表的模版資訊
     v_xmltemp := '<'||V_DataSyncCfg.TABLE_NAME||'  InsertTemplate="'||V_DataSyncCfg.insert_template||'"  DeleteTemplate="'||V_DataSyncCfg.delete_template||'" OrdernNo="'||V_DataSyncCfg.order_no||'" ExecType="'||v_exectype||'">';
     execute immediate v_commsql using V_DataSyncCfg.TABLE_NAME,v_xmltemp,sysdate,v_orderno;
     v_orderno :=v_orderno+1;
     --插入刪除條件模版
     v_xmltemp := '<'||V_DataSyncCfg.TABLE_NAME||'DelCol DeleteCol="'||V_DataSyncCfg.DELETE_CONDITION||'"></'||V_DataSyncCfg.TABLE_NAME||'DelCol>';
     execute immediate v_commsql using V_DataSyncCfg.TABLE_NAME,v_xmltemp,sysdate,v_orderno;
     v_orderno :=v_orderno+1;
    --插入資料型別模版
     v_xmltemp := V_DataSyncCfg.data_type_template;
     execute immediate v_commsql using V_DataSyncCfg.TABLE_NAME,v_xmltemp,sysdate,v_orderno;
     v_orderno :=v_orderno+1;
   --時間標籤不區分機組
   -------------------------------BEGIN---------------------------------------------------------------------------------
   ----------------------不區分機組的時間標籤開始----------------------------------------------------------------------
   --------------------------------------------------------------------------------------------------------------------
   IF V_DataSyncCfg.TIMETAG_TYPE=1 THEN
   BEGIN
   --獲取上次更新結束時間
   BEGIN
    SELECT END_TIME INTO V_BEGIN_DATE FROM TB_PUB_SYNC_TIMESEG_TAG WHERE TABLE_NAME=V_DataSyncCfg.TABLE_NAME;
    EXCEPTION WHEN NO_DATA_FOUND THEN
    V_BEGIN_DATE := SYSDATE-365;
   END;
   --如果時間型別為系統時間
   IF V_DataSyncCfg.SYNCTIME_TYPE=0 THEN
    V_END_DATE := SYSDATE;
   --如果時間型別為資料時間
   ELSE
   EXECUTE IMMEDIATE 'SELECT MAX('||V_DataSyncCfg.COMPARE_DATE_COL||') FROM '||V_DataSyncCfg.TABLE_NAME  INTO V_END_DATE;
   END IF;

   IF V_END_DATE IS NULL OR V_END_DATE<=V_BEGIN_DATE THEN
     GOTO LABEL_NEXT_TABLE_SYNC;
   END IF;

   V_TEMP_SQL  :=V_DataSyncCfg.data_xmltemplate;
   V_TEMP_SQL  :=REPLACE(V_TEMP_SQL,'{BEGIN_DATE}','to_date('''||to_char(V_BEGIN_DATE,'yyyy-mm-dd hh24:mi:ss')||''',''yyyy-mm-dd hh24:mi:ss'')');
   V_TEMP_SQL  :=REPLACE(V_TEMP_SQL,'{END_DATE}','to_date('''||to_char(V_END_DATE,'yyyy-mm-dd hh24:mi:ss')||''',''yyyy-mm-dd hh24:mi:ss'')');
   --dbms_output.put_line(V_TEMP_SQL);
   ------------------------------BEGIN----------------------------------------------------------------------------------
   ----------------------開始執行動態遊標----------------------------------------------------------------------
   --------------------------------------------------------------------------------------------------------------------
   --動態執行模版SQL
   OPEN CUR_SQL FOR V_TEMP_SQL;
   LOOP
   EXIT WHEN CUR_SQL%NOTFOUND;
   FETCH CUR_SQL  INTO V_SQL;
   IF V_SQL IS NOT NULL THEN
   --將結果寫入表中
   V_SYNC_TIME := SYSDATE;
   execute immediate v_commsql using V_DataSyncCfg.TABLE_NAME,V_SQL,V_SYNC_TIME,v_orderno;
   v_orderno :=v_orderno+1;
   V_SQL := NULL;
   END IF;
   END LOOP;
   --------------------------------------------------------------------------------------------------------------------
   ----------------------結束執行動態遊標----------------------------------------------------------------------
   ---------------------------END--------------------------------------------------------------------------------------
   MERGE INTO TB_PUB_SYNC_TIMESEG_TAG T USING (SELECT V_DataSyncCfg.TABLE_NAME TABLE_NAME FROM DUAL) T1
   ON (T.TABLE_NAME=T1.TABLE_NAME)
   WHEN MATCHED THEN
   UPDATE SET END_TIME=V_END_DATE,BEGIN_TIME=V_BEGIN_DATE,UPDATE_TIME=SYSDATE
   WHEN NOT MATCHED THEN
   INSERT VALUES(V_DataSyncCfg.TABLE_NAME,'','',V_BEGIN_DATE,V_END_DATE,SYSDATE);
   END;
   --------------------------------------------------------------------------------------------------------------------
   ----------------------不區分機組的時間標籤結束----------------------------------------------------------
   ----------------------------END-------------------------------------------------------------------------------

   -------------------------------BEGIN-------------------------------------------------------------------------------
   ----------------------時間標籤區分機組開始----------------------------------------------------------------------
   --------------------------------------------------------------------------------------------------------------------
   --時間標籤區分機組,這種是出現表中沒有UPDATE_TIME的情況下
    ELSE
    BEGIN
    SELECT FACTORY_CODE, SET_CODE BULK COLLECT INTO V_FACTORY_CODE_LIST, V_SET_CODE_LIST FROM V_PUB_SET WHERE IS_VIRTUAL<>1 ORDER BY FACTORY_CODE, SET_CODE desc;

   ----------------------------BEGIN-----------------------------------------------------------------------------------
   ----------------------迴圈機組列表開始----------------------------------------------------------------------
   --------------------------------------------------------------------------------------------------------------------
    --迴圈機組列表
    FOR I IN 1..V_SET_CODE_LIST.COUNT LOOP
    --獲取開始時間
    BEGIN
    SELECT END_TIME INTO V_BEGIN_DATE FROM TB_PUB_SYNC_TIMESEG_TAG WHERE TABLE_NAME=V_DataSyncCfg.TABLE_NAME AND SET_CODE=V_SET_CODE_LIST(I) AND FACTORY_CODE=V_FACTORY_CODE_LIST(I);
    EXCEPTION WHEN NO_DATA_FOUND THEN
    V_BEGIN_DATE := SYSDATE-365;
    WHEN OTHERS THEN
    GOTO LABEL_NEXT_SET;
    END;
    --如果時間型別為系統時間
    IF V_DataSyncCfg.SYNCTIME_TYPE=0 THEN
    V_END_DATE := SYSDATE;
    --如果時間型別為資料時間
    ELSE
    BEGIN
    EXECUTE IMMEDIATE 'SELECT MAX('||V_DataSyncCfg.COMPARE_DATE_COL||')  FROM '||V_DataSyncCfg.TABLE_NAME||' WHERE SET_CODE='||V_SET_CODE_LIST(I)||'
    AND FACTORY_CODE='''||V_FACTORY_CODE_LIST(I)||''''  INTO V_END_DATE;
    EXCEPTION WHEN OTHERS THEN
    GOTO LABEL_NEXT_SET;
    END;
    END IF;

    IF V_END_DATE IS NULL OR V_END_DATE<=V_BEGIN_DATE  THEN
     GOTO LABEL_NEXT_SET;
    END IF;

    V_TEMP_SQL :=V_DataSyncCfg.data_xmltemplate;
    V_TEMP_SQL :=REPLACE(V_TEMP_SQL,'{BEGIN_DATE}','to_date('''||to_char(V_BEGIN_DATE,'yyyy-mm-dd hh24:mi:ss')||''',''yyyy-mm-dd hh24:mi:ss'')');
    V_TEMP_SQL :=REPLACE(V_TEMP_SQL,'{END_DATE}','to_date('''||to_char(V_END_DATE,'yyyy-mm-dd hh24:mi:ss')||''',''yyyy-mm-dd hh24:mi:ss'')');
    V_TEMP_SQL :=REPLACE(V_TEMP_SQL,'{FACTORY_CODE}',''''||V_FACTORY_CODE_LIST(I)||'''');
    V_TEMP_SQL :=REPLACE(V_TEMP_SQL,'{SET_CODE}',''''||V_SET_CODE_LIST(I)||'''');

    --dbms_output.put_line(V_TEMP_SQL);
   -------------------------------BEGIN--------------------------------------------------------------------------------
   ----------------------開始執行動態遊標----------------------------------------------------------------------
   --------------------------------------------------------------------------------------------------------------------
    --開始執行動態遊標
    OPEN CUR_SQL FOR V_TEMP_SQL;
    LOOP
    EXIT WHEN CUR_SQL%NOTFOUND;
    FETCH CUR_SQL  INTO V_SQL;
    IF V_SQL IS NOT NULL THEN
    --將結果寫入表中
    V_SYNC_TIME := SYSDATE;
    execute immediate v_commsql using V_DataSyncCfg.TABLE_NAME,V_SQL,V_SYNC_TIME,v_orderno;
    v_orderno :=v_orderno+1;
    V_SQL := NULL;
    END IF;
    END LOOP;
   --------------------------------------------------------------------------------------------------------------------
   ----------------------結束執行動態遊標----------------------------------------------------------------------
   -----------------------------END------------------------------------------------------------------------------------
    MERGE INTO TB_PUB_SYNC_TIMESEG_TAG T USING (SELECT V_DataSyncCfg.TABLE_NAME TABLE_NAME,V_FACTORY_CODE_LIST(I) FACTORY_CODE,V_SET_CODE_LIST(I) SET_CODE FROM DUAL) T1
    ON (T.TABLE_NAME=T1.TABLE_NAME AND T.FACTORY_CODE=T1.FACTORY_CODE AND T.SET_CODE=T1.SET_CODE)
    WHEN MATCHED THEN
    UPDATE SET END_TIME=V_END_DATE,BEGIN_TIME=V_BEGIN_DATE,UPDATE_TIME=SYSDATE
    WHEN NOT MATCHED THEN
    INSERT VALUES(V_DataSyncCfg.TABLE_NAME,V_FACTORY_CODE_LIST(I),V_SET_CODE_LIST(I),V_BEGIN_DATE,V_END_DATE,SYSDATE);
     --每個機組提交一次
    <<LABEL_NEXT_SET>>
    NULL;
    END LOOP;
   --------------------------------------------------------------------------------------------------------------------
   ----------------------迴圈機組列表結束----------------------------------------------------------------------
   -----------------------------END-----------------------------------------------------------------------------------

    END;
    END IF;
    --------------------------------------------------------------------------------------------------------------------
    ----------------------時間標籤區分機組結束----------------------------------------------------------
    ------------------------------END-----------------------------------------------------------------------------------

    --插入表接點結束符
    execute immediate v_commsql using V_DataSyncCfg.TABLE_NAME,'</'||V_DataSyncCfg.TABLE_NAME||'>',sysdate,v_orderno;
    v_orderno:=v_orderno+1;
    --如果是手動同步,則同步一次即修改同步標識,標識為不同步
    IF V_DataSyncCfg.SYNC_TYPE=0 AND V_DataSyncCfg.IS_SYNC=1 THEN
    UPDATE TB_PUB_SYNC_DATA_CFG_NEW SET IS_SYNC=0 WHERE upper(TABLE_NAME)=upper(V_DataSyncCfg.TABLE_NAME);
    END IF;
    <<LABEL_NEXT_TABLE_SYNC>>
     null;
    END LOOP;
    --插入根節點結束符
    execute immediate v_commsql using '','</XMLROOT>',sysdate,v_orderno;
    --更新資料同步狀態為‘1’已完成,這時後臺服務可以呼叫
    execute immediate 'update TB_PUB_SYNC_TIMESEG_TAG set factory_code=1,set_code=1,begin_time=sysdate,end_time=sysdate,update_time=sysdate where table_name=''SYNCSTATUSTAG''';   
    COMMIT;
   EXCEPTION WHEN OTHERS THEN
   ROLLBACK;
 END P_PUB_JOB_DATA_SYNC_New;

上面列出的就是資料庫的兩個核心儲存過程,使用job定時去執行P_PUB_JOB_DATA_SYNC_New

然後使用查詢是,用tb_pub_sync_data_sql表中的order_no欄位 排序,這樣能保證XML的完整性

3)使用後臺服務定時讀取tb_pub_sync_data_sql中的資料去生成檔案,生成的檔案格式如下:

<?xml version="1.0" encoding="utf-8" ?>

<XMLROOT>

--該節點儲存表的插入和刪除模版以及更新方式

<表名  InsertTemplate=""  DelteTemplate=""  ExecType=""  Order_No="">

--該節點儲存,刪除時需要用那些欄位來做條件,多個欄位用逗號隔開,該節點每張表只會寫一次

<表名DelCol  DeleteCol="col1,col2,col3"></表名DelCol DelCol>

--該節點儲存表中各欄位的資料型別,用於程式進行資料轉換,該節點每張表只會寫一次

<表名ColType col1="Varchar2" col2="Number" col3="Varchar2"></表名ColType>

--該節點用於儲存資料,一條資料對應一個節點

<表名DataRow col1="12" col2="23" col3="45"></表名DataRow>

</表名>

</XMLROOT>

3)將檔案壓縮打包,然後通過傳輸服務將檔案傳送到Ⅲ區伺服器指定的目錄

4)Ⅲ區伺服器上的資料同步服務,讀取指定目錄下的XML檔案進行解析,轉換成目標格式,下面貼出主要的程式碼

程式碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DataSyncSvr.DataEntity;
using Oracle.DataAccess.Client;
using DataSyncSvr.DataParse;
using Publish.Log;
using System.IO;
using System.Data;

namespace DataSyncSvr
{
    public class DataSyncMain
    {
        public ILogger mlog;
        private OracleConnection conn;
        public void DataSyncStart()
        {
            ParseXmlToDataEntity ParseEntity = new ParseXmlToDataEntity();
            Dictionary<string, Dictionary<string, DataSyncDataEntity>> FileList = ParseEntity.GetDataEnetityList();
            Dictionary<string, DataSyncDataEntity> EntityDataList;
            conn = new OracleConnection(SyncConst.Connstr);
            if (conn.State == ConnectionState.Closed)
            {
                conn.Open();
            }
            DataSyncDataEntity EntityData;
            if (FileList == null || FileList.Keys.Count < 1) return;
            foreach(string filekey in FileList.Keys)
            {
                EntityDataList=FileList[filekey];
                foreach (string key in EntityDataList.Keys)
                {
                    try
                    {
                        EntityData = EntityDataList[key];
                        mlog.LogInfo("開始同步表:\"" + key + "\"");
                        if (EntityData.ExecuteType == ExecType.DeleteAndInsert || EntityData.ExecuteType == ExecType.TruncateAndInsert)
                        {
                            //先執行刪除操作
                            AddExecParamAndRun(EntityData, ExecType.Delete);
                            //再執行插入操作
                            AddExecParamAndRun(EntityData, ExecType.Insert);
                        }
                        else
                        {
                            AddExecParamAndRun(EntityData, ExecType.Insert);
                        }
                        mlog.LogInfo("\"" + key + "\"表資料同步完成,受影響行數:(" + EntityData.RecordCount + ")行");
                      
                    }
                    catch (Exception ex)
                    {
                        mlog.LogInfo(ex.ToString());
                        break;
                    }
                }
                //刪除檔案
                if (File.Exists(filekey))
                {
                    File.Delete(filekey);
                    mlog.LogInfo("檔案:\"" + filekey + "\"已刪除");
                }
            }
            conn.Close();
        }
        private void AddExecParamAndRun(DataSyncDataEntity EntityData, ExecType excutetype)
        {
            OracleParameter Param;
            string[] columns = EntityData.InsertCol;
            string ExecTemplate = EntityData.InsertTemplate;
            if (excutetype.Equals(ExecType.Delete))
            {
                columns = EntityData.DeleteCol;
                ExecTemplate = EntityData.DeleteTemplate;
            }
            OracleCommand command = new OracleCommand();
            command.Connection = conn;
            command.CommandText = ExecTemplate;
            command.ArrayBindCount = EntityData.TableData[EntityData.InsertCol[0]].Length;
            command.CommandTimeout = 600;
            if (columns != null && columns.Length > 0)
            {
                foreach (string colname in columns)
                {
                    if (!string.IsNullOrEmpty(colname))
                    {
                        Param = new OracleParameter(colname, EntityData.DataType[colname]);
                        Param.Direction = ParameterDirection.Input;
                        Param.Value = EntityData.TableData[colname];
                        command.Parameters.Add(Param);
                    }
                }
            }
            command.ExecuteNonQuery();
        }
    }
}

注意:使用了Oracle.DataAccess.dll動態庫,這個可以去官網下載。

獻醜了,嘿嘿!

QQ:936052556;Email:[email protected]或者QQ郵箱也行