一个加油站实时监控系统,加油站每加完一次油数据自动上传,
oracle8.05 远程数据库,采用ODBC连接,从CRecordSet继承来的类,
由于网络不好经常断线,所以写入数据经常丢失,而且程序也死掉了,
有时甚至出现数据库中数据表锁死现象,造成数据不能更新和插入,已经发生过,
怎样能在程序中判断连接的状态,同时又对程序的实时性没有影响?
请指教~~

解决方案 »

  1.   

    我个人的看法,不知对不对
    1、使用事务,即使断线了也能确保数据的一致性。
    2、捕捉错误事件,判断连接是否已断开,如果是马上再连上。
    3、设定一个最佳的timeout时间,使得程序不致于死机和处理事务的时间不能太长,又不能老是断线出错。
      

  2.   

    我现在用的是事务处理,可是等待时间太长,而且网络数据库用的是从CRecordSet继承来的,
    用try执行 catch捕捉所有错误,可是经常捕捉不到,加断点根本就没有执行完try就跳出了,
    所以一旦断网,本以为事务处理能保证数据的一致性,我是暂时把不能提交远程数据库的数据
    存到本地了,如果不能正常处理连接错误的话,还是会出现程序崩溃。重新连接数据库我不知道怎么实现,不过好像在超时限定内重新把拔掉的网线结上,一切正常。
    判断连接是否断开?这正是我要问的问题,我不会啊:)超时设置也没有用过,只是知道可以设置,我用了CDatabase和CRecordSet继承来的数据集相关联
    ,超时不知道怎么设置。请多多关照:)
      

  3.   

    CDatabase::SetQueryTimeout();设定查询超时,当sql 语句(包括存储过程)执行超过这个时间时就会出错。这个出错可以用try和catch来捕捉的。你可以估算一下,执行一条sql 语句大约需要多长时间,超过这个时间你可以认为是连接中断了。
    中断后你可以再重新建立一个新的连接。
    一个事务尽可能的短,否则用户多了有可能会造成数据库中数据表锁死现象
    因为我没有做过远程连接,这也仅仅是我的猜测,也不知对不对
      

  4.   

    我现在把打开数据库的操作也放在了try catch 块内,不过要是在执行到BeginTrans()这里断线的话,那还是没有办法,程序只有死掉了现在我又遇到了另外一个问题,就是连续写数据库时,写到123个纪录后,程序莫名其妙的停下,
    就好像进入了死循环,代码如下
     
          CDatabase *pdb=&(((CjyApp*)AfxGetApp())->db);
          CMyData  set;
          int num=1000;
          for(int i=1;i<999;i++)
          {
            pdb->begintrans();
            try{
              CString pzh,strFilter;
              pzh.Format("%d",num+i);
              strFilter.Format("pzh='%s'",pzh);
              if(set.IsOpen())set.Close();
              set.strFilter=strFilter;
              set.Open();
              if(set.GetRecordCount()>0)
              {
                 set.Close();
                 pdb->CommitTrans();
                 continue;
               }
              set.AddNew();
              set.m_RQ=CTime::GetCurrentTime();
              ……//具体13个数据,为float 和 CString型
              set.UpData();
              pdb->CommitTrans();
             }
             catch(CException *pe)
             {
                pe->ReportError();
                pe->Delete();
                pdb->Rollback();
              }
              if(set.IsOpen())
                 set.Close();
          }
      

  5.   

    我改了一下你程序,我自己好好下看一下,这这里,set.GetRecordCount()>0不会得到正确的结果的,我不知道你想干什么,所以没改。事务提交一般是做完一定内容的数据更新且没有问题才提交的。可能你的程序问题都是由这里引起的。
    CDatabase *pdb=&(((CjyApp*)AfxGetApp())->db);
          CMyData  set;
          int num=1000;
    pdb->begintrans();
     try{      for(int i=1;i<999;i++)
          {
             CString pzh,strFilter;
              pzh.Format("%d",num+i);
              strFilter.Format("pzh='%s'",pzh);
              if(set.IsOpen())set.Close();
              set.strFilter=strFilter;
              set.Open();
              if(set.GetRecordCount()>0)
              {
                 set.Close();
                 pdb->CommitTrans();
                 continue;
               }
              set.AddNew();
              set.m_RQ=CTime::GetCurrentTime();
              ……//具体13个数据,为float 和 CString型
              set.UpData();
              
             
              if(set.IsOpen())
                 set.Close();
          }
    }
    catch(CException *pe)
             {
                pe->ReportError();
                pe->Delete();
                pdb->Rollback();
    if(set.IsOpen())
                 set.Close();
     return ;
              }
              if(set.IsOpen())
                 set.Close();
    pdb->CommitTrans();
      

  6.   

    还有一个地方没改。
    CDatabase *pdb=&(((CjyApp*)AfxGetApp())->db);
          CMyData  set;
          int num=1000;
    pdb->begintrans();
     try{      for(int i=1;i<999;i++)
          {
             CString pzh,strFilter;
              pzh.Format("%d",num+i);
              strFilter.Format("pzh='%s'",pzh);
              if(set.IsOpen())set.Close();
              set.strFilter=strFilter;
              set.Open();
              if(set.GetRecordCount()>0)
              {
                 set.Close();
                 
                 continue;
               }
              set.AddNew();
              set.m_RQ=CTime::GetCurrentTime();
              ……//具体13个数据,为float 和 CString型
              set.UpData();
              
             
              if(set.IsOpen())
                 set.Close();
          }
    }
    catch(CException *pe)
             {
                pe->ReportError();
                pe->Delete();
                pdb->Rollback();
    if(set.IsOpen())
                 set.Close();
     return ;
              }
              if(set.IsOpen())
                 set.Close();
    pdb->CommitTrans();
      

  7.   

    我在这里有个索引:  pzh
              CString pzh,strFilter;
              pzh.Format("%d",num+i);
              strFilter.Format("pzh='%s'",pzh);
              if(set.IsOpen())set.Close();
              set.strFilter=strFilter;
              set.Open();
              if(set.GetRecordCount()>0)
              {
                 set.Close();
                 pdb->CommitTrans();
                 continue;
               }
           
    先检查凭证号有没有重复,如果有重复set.GetRecordCount()  会返回 1 ,
    如果有返回值关闭记录集,结束事务
      

  8.   

    ODBC中事务不能嵌套的,如果出错之后先执行   Rollback()就已经结束了事务;
    之后又执行 CommitTrans();可能会出错的