公司要求每隔10秒,把mssql中的数据插入到oracle数据库中,我现在改用了多线程来执行.我在 terimer事件中,执行 createthread(),但发现oracel数据库中有好多重复的数据,不知怎么解决?

解决方案 »

  1.   

    一般,timer和线程 只要使用一种就行了
    timer事件中执行insert不行吗?为什么还要使用线程?oracel数据库中有好多重复的数据,则是另一个问题了
    想删除,还是想不让它再产生?这就需要很具体的信息了
      

  2.   

    回楼上,我很多个数据库中有多个表要插入到oracle数据库对应表中。如果直接用timer的话,很慢并且界面会死的。所以我想用在timer中10秒钟来执行一次线程插入(把最打的数据从mssql中插入到oracle中)。
    我感觉我在 timer和线程处理不好, 当线程还没有完成插入时,有可以 timer再触发一次,这样有可能插入重复数据了。不知怎么处理这两者的关系?
      

  3.   

    回楼上,我很多个数据库中有多个表要插入到oracle数据库对应表中。如果直接用timer的话,很慢并且界面会死的。所以我想用在timer中10秒钟来执行一次线程插入(把最新的数据从mssql中插入到oracle中)。
    我感觉我在 timer和线程处理不好, 当线程还没有完成插入时,有可能 timer再触发一次,这样有可能插入重复数据了。不知怎么处理这两者的关系?上面打错字了
      

  4.   

    那就一个线程来插入好了,插完它自己sleep(10000);然后接着插
    不用定时器
      

  5.   

    我自己写段代码function getdata(p:pointer):boolean;stdcall;
      var
        str:string;
        id:integer;
    Begin  Coinitialize(nil);
      EnterCriticalSection(cs);
      form1.ADOQuery1.Close;
      form1.ADOQuery1.SQL.Clear;
      form1.ADOQuery1.SQL.Add('select count(1) from overtime1') ;
      form1.ADOQuery1.Open;
      if form1.ADOQuery1.RecordCount=0 Then
        id:=0
       else
        id:=form1.ADOQuery1.Fields[0].AsInteger;  str:='INSERT INTO overtime1(number,person_number,kind,id) SELECT number,person_number,kind,id FROM overtime WHERE id ' +
            ' > '+inttostr(id)+' and id < '+inttostr(id+11)+' ORDER BY id ';
      form1.ADOQuery1.Close;
      form1.ADOQuery1.SQL.Clear;
      form1.ADOQuery1.SQL.Add(str);
      form1.ADOQuery1.ExecSQL;
      LeaveCriticalSection(cs);
    end;procedure TForm1.Timer1Timer(Sender: TObject);
      var
        wd:Dword;
    begin
      Createthread(nil,0,@getdata,nil,0,wd);
    end;
    我哪怕把timer的间隔设为 100 ,结果都很正常。我不知公司的代码不行????
      

  6.   

    由于公司不能上网,所以代码发不出来。上段代码我现在在家写的,完全OK!我现在想想,是不是我线程里面有 事务导致的, begintran 和 committran 等,
    因为oracel和mssql有点不一样,orcacle插入后一定要 commit.但现在我也不能确定是什么引起重复数据。
      

  7.   

    重复可能是定时器多次触发了几个线程导致的?
    改为单线程自行循环插,应该没问题了另外,靠count(1)作为后面id的依据,好像不大可靠:万一中间删掉过记录。
    应该以max(id)作为后面id的依据才对
      

  8.   

    谢谢提醒,因为这个表是现在建的。可恶的是公司不能上网,把代码发上来就好了。
    我的本意是 先把 timer禁用,再执行线程,等线程执行完,再把timer启用。但这样比较难控制,不知sz_haitao有什么好的办法
      

  9.   

    可以在timer时间里判断线程是否还在执行,是则忽略,否则执行
      

  10.   

    不需要用timer,只用1个线程就好了吧,每次结束就延时10秒再继续
    数据是否重复,那是插入数据代码没处理好,除非有并发的情况,否则和线程没关系
      

  11.   

    精确一点,就用线程,在线程的回调函数中,再次调用线程API函数.是可行的.
    当然中间SLEEP(10000)
      

  12.   


    可以这样.在线程执行完毕时,向主窗口发送一个消息,设置一个变量,TIMER里面每都检查这个变量.余下的我就不说了吧.
      

  13.   

    其实很简单,在Timer事件里运行时 先enabled := false; 执行完入库,再enabled := True; 就好!
      

  14.   

    function CreateWaitableTimer(
      lpTimerAttributes: PSecurityAttributes; {安全}
      bManualReset: BOOL;    {True: 可调度多个线程; False: 只调度一个线程}
      lpTimerName: PWideChar {名称}
    ): THandle; stdcall;     {返回句柄}function SetWaitableTimer(
      hTimer: THandle;                         {句柄}
      var lpDueTime: TLargeInteger;            {起始时间}
      lPeriod: Longint;                        {间隔时间}
      pfnCompletionRoutine: TFNTimerAPCRoutine;{回调函数的指针}
      lpArgToCompletionRoutine: Pointer;       {给回调函数的参数}
      fResume: BOOL                            {是否唤醒系统}
    ): BOOL; stdcall;                          {}
      

  15.   

    看了下问题,LZ好像不是在每隔十秒执行插入出问题,而是在插入数据的冗余判断出问题,可以这样,在sql数据库中设立一个同步标记,默认true,插入oracle后改为false,线程插入函数中修改标记部分加锁,保证多个线程不会同时插入相同的数据,或者把插入函数枷锁也可以,不过那样就没必要多线程,一个线程足够了
      

  16.   

    或者可以用存储过程, 预先写好存储过程, 在插入的时候在存储过程中检查是否有重复或者直接把这个键设置成 主键或者不可重复////===================================================用计时器来触发线程,真还不如直接在线程里面  sleep
      

  17.   

    如果不是为了效率,只要一个线程插入就足够了确保同时只有一个线程在执行
    如果还有重复,那就是sql的逻辑问题了
      

  18.   

    晕,单用线程就可以处理这个问题呀,你用Time倒不好!
      

  19.   

    很好处理,在Timer的OnTimer事件中这样写
    Timer.Enable := false; //关闭定时器
    width Thread.Create do
      OnTerminate := CloseSyncThread; //注意此处,CloseSyncTherad是线程执行完毕释放时的事件。定义如下:
      procedure CloseSyncThread(Sender:TObject);
      begin
        Timer.Enable := true; //启动定时器
      end;在线程里加入FreeOnTerminate:=true;  //线程结束时,自动释放资源
    这就是一个完整的循环了!
      

  20.   

    今天一天没来,就这么多回复。太好了,这个问题我已经解决了。是采取sz_haitao说的方法。
    其实线程和timer没有多少影响,timer可以控制好线程。数据重复是因为oracle表结构有问题,它只存了
    yyyy-mm-dd hh:nn:ss 并没有保存毫秒。所以我把这字段改 timestamp就可以了。