软件用delphi开发,c/s结构:数据库+客户端软件。在客户端程序中有多个线程在执行,都可能需要与数据库交互(通过ado组件)。如果这多个线程用一个连接的话,怕会出现问题,因为我从晚上了解到adoconnection不是线程安全的。所以,想做一个连接池(从java连接池得到的启发),哪个线程需要查数据库,就从池里取一个连接,用完了再放回池。自己做了一下,老是调不通。看来做这东西挺复杂的(我可能比较菜),请问各位有谁做过连接池的,或有没有知道有现成的可以使用。非常感激!

解决方案 »

  1.   

    to magicjove :“每次需要连接时创见个连接,从池子取出需要的连接复制给新建连接 ”,用连接池的目的就是为了防止每次创建连接花费的时间,这样做的话,要池没有意义了呀。
      

  2.   

    看看下面的连接内容是否有用
    http://hdw802.blog.163.com/blog/static/238868620088271123562/
    Delphi使用ADO连接池(存储过程示例)
      

  3.   

    試過一次,不過真沒得到大的用處。
    當時是導幾幾百個G的數據時候用的。
    1.  開啟一個程序後
       TMyList : Tlist;
       啟動後建立一定量的Connection  , 做個池的作用。   後面跟一個狀態2.  其中一個線程中 ADOQUERY  需要處理數據去請求  TMylist  中的連接,當然這裏你要寫一個 管理池的功能,如果池中的連接都未使用,就分配給他。
        如果池中的連接用完了,就給它信息,等待  或增加池   ,   Tadoquery  使用後,通知池,釋放關系。空中池中的連接
      

  4.   

    to:starluck大侠。
    思路我当然明白,但是写程序时要处理好多线程synchronized还是没取到时的排队、空闲连接的释放等细节问题。如果有现成,最好用现成的。
      

  5.   

     不好意思,現成的真沒有了,那時早幾年在BDE寫的一個東西。 這個東西你只要考慮下  TManageThreadlist   實現這個池。  1.  請求連接函數,返回 connection
      2.  釋入連接函數, 空置一個Connection   等這些,如果非特別大的項目裏用的話,這個自己實現一些簡單的管理 不是很難的啊。
    我到時覺得思路有了,自己實現應該可以的吧。
      

  6.   

    这个老外讲得好啊:http://dn.embarcadero.com/article/30027
      

  7.   

    自己做的一个,用了很久了,没发现有什么问题,
    唯一的问题就是,连接数越多,启动越慢,因为要先创建在那儿,不过你可以修改为使用时创建也可以,
    这样就可以避免启动时慢的问题unit dbpool;interfaceuses
      DB, ADODB, classes, Dialogs, SysUtils;
      
    type
      TDbObjPool  = record
        Flag: boolean;                //当前对象是否被使用
        ConnObj: TADOConnection;      //数据库连接对象
        QryObj: TADOQuery;            //数据库访问对象
      end;  {处理数据库连接池类}
      TDbPoolClass = class
      private
        { Private declarations }
        DB_POOL_NUMBER:integer;
        localConnStr:string;
        DbObjPool:array[1..30] of TDbObjPool;  public
        { Public declarations }
        constructor Create(const paPwd,paUser,paDS,paDB:string);overload;
        destructor Destroy;override;    procedure InitDbPool;    function  GetNewQuery(const paIndex:integer):TADOQuery;
        procedure FreeQuery(const paIndex: integer);
        function  GetQueryFromPool(): integer;
        function  getPoolUseNum():integer;  end;var
      dbPoolClass:TDbPoolClass;
      
    implementation//**:***************************************************************************
    //**:功能:设置数据库连接字符串.并测试数据库连接,如果连接失败,终止应用程序
    //**:输入:paPwd:数据库访问密码
    //**:      paUser:数据库访问用户
    //**:      paDS:ODBC数据源
    //**:      paDB:要访问的数据库名称
    //**:***************************************************************************
    constructor TDbPoolClass.Create(const paPwd,paUser,paDS,paDB:string);
    begin
      DB_POOL_NUMBER := length(DbObjPool);       //记录连接池允许最大连接个数
      
      //根据ODBC配置信息,构造连接字符串。
      localConnStr := 'Provider=MSDASQL.1;Persist Security Info=False;' +
                    'Password=' + paPwd + ';User ID=' + paUser +
                    ';Data Source=' + paDS + ';Initial Catalog=' + paDB;  //建立数据库连接。如果连接失败,停止应用程序执行。
      try
        InitDbPool;
      except
        raise Exception.Create('连接数据库('+paDB+')失败!');
      end;
    end;
    //**:***************************************************************************
    //**:功能:释放线程池中的所有连接对象
    //**:***************************************************************************
    destructor TDbPoolClass.Destroy;
    var
      i:integer;
    begin
      for i:=1 to DB_POOL_NUMBER do
      begin
        DbObjPool[i].Flag := false;
        DbObjPool[i].ConnObj.free;        DbObjPool[i].ConnObj := nil;
        DbObjPool[i].QryObj.free;         DbObjPool[i].QryObj := nil;
      end;
    end;//**:***************************************************************************
    //**:功能:数据库连接池的对象,并使对象保持连接
    //**:***************************************************************************
    procedure TDbPoolClass.InitDbPool;
    var
      i:integer;
    begin
      for i:=1 to DB_POOL_NUMBER do
      begin
        DbObjPool[i].Flag := false;
        DbObjPool[i].ConnObj := TADOConnection.Create(nil);
        DbObjPool[i].QryObj := TADOQuery.Create(nil);    DbObjPool[i].ConnObj.ConnectionString := localConnStr;
        DbObjPool[i].QryObj.Connection := DbObjPool[i].ConnObj;
        DbObjPool[i].QryObj.LockType := ltOptimistic;
        DbObjPool[i].ConnObj.LoginPrompt := False;
        DbObjPool[i].QryObj.Connection.CommandTimeout := 3600;
        DbObjPool[i].QryObj.CommandTimeout := 3600;    DbObjPool[i].ConnObj.Connected := True;
      end;
    end;//**:***************************************************************************
    //**:功能: 取得当前数据库连接使用个数
    //**:***************************************************************************
    function TDbPoolClass.getPoolUseNum():integer;
    var
      i,j:integer;
    begin
      j := 0;
      for i:=1 to DB_POOL_NUMBER do
        if DbObjPool[i].Flag then inc(j);
      result := j;
    end;//**:***************************************************************************
    //**:功能:取得指定序号的数据库连接池中的数据库访问对象.
    //**:***************************************************************************
    function TDbPoolClass.GetNewQuery(const paIndex:integer):TADOQuery;
    begin
      if ((paIndex<1) or (DB_POOL_NUMBER<paIndex)) then
        raise Exception.Create('尚未申请数据库访问对象.');
      if not DbObjPool[paIndex].Flag then
        raise Exception.Create('数据库连接池访问发生混乱.');  DbObjPool[paIndex].QryObj.Close;
      DbObjPool[paIndex].QryObj.SQL.Clear;  result := DbObjPool[paIndex].QryObj;
    end;
    //**:***************************************************************************
    //**:功能:释放指定的数据库连接对象
    //**:***************************************************************************
    procedure TDbPoolClass.FreeQuery(const paIndex: integer);
    begin
      if ((0<paIndex) and (paIndex<(DB_POOL_NUMBER+1))) then
        DbObjPool[paIndex].Flag := false;
    end;//**:***************************************************************************
    //**:功能:从数据库连接池中申请数据库访问对象.
    //**:返回:该对象的序号.
    //**:***************************************************************************
    function TDbPoolClass.GetQueryFromPool(): integer;
    var
      i,j:integer;
    begin
      j := 0;
      while 1=1 do
      begin
        inc(j);
        if j>1000 then raise Exception.Create('等待申请数据库连接对象失败');    for i:=1 to DB_POOL_NUMBER do
          if not DbObjPool[i].Flag then
          begin
            DbObjPool[i].Flag := true;
            result := i;
            exit;    //申请到对象,返回
          end;
        sleep(5);    //等待5毫秒继续申请,直至超时.
      end;
    end;end.
      

  8.   

    to:wgzymzx这位热情大方的大侠。
    你的连接池没有做同步处理,在多线程使用时会出现问题。
      

  9.   

    要不参考一下:http://download.csdn.net/source/396131
      

  10.   

    to:介绍Delphi使用ADO连接池(存储过程示例) 的同仁。这个我看过了,我要的是数据库连接池,不是具体到ado甚而这个和ado有很强的耦合。不是我想要的效果,而且这个功能也不全。大家可以看一下java的连接池,作得相当好。
      

  11.   

    连接池没做过,思路差不多。。
    帮LZ up!