软件用delphi开发,c/s结构:数据库+客户端软件。在客户端程序中有多个线程在执行,都可能需要与数据库交互(通过ado组件)。如果这多个线程用一个连接的话,怕会出现问题,因为我从晚上了解到adoconnection不是线程安全的。所以,想做一个连接池(从java连接池得到的启发),哪个线程需要查数据库,就从池里取一个连接,用完了再放回池。自己做了一下,老是调不通。看来做这东西挺复杂的(我可能比较菜),请问各位有谁做过连接池的,或有没有知道有现成的可以使用。非常感激!
调试欢乐多
http://hdw802.blog.163.com/blog/static/238868620088271123562/
Delphi使用ADO连接池(存储过程示例)
當時是導幾幾百個G的數據時候用的。
1. 開啟一個程序後
TMyList : Tlist;
啟動後建立一定量的Connection , 做個池的作用。 後面跟一個狀態2. 其中一個線程中 ADOQUERY 需要處理數據去請求 TMylist 中的連接,當然這裏你要寫一個 管理池的功能,如果池中的連接都未使用,就分配給他。
如果池中的連接用完了,就給它信息,等待 或增加池 , Tadoquery 使用後,通知池,釋放關系。空中池中的連接
思路我当然明白,但是写程序时要处理好多线程synchronized还是没取到时的排队、空闲连接的释放等细节问题。如果有现成,最好用现成的。
2. 釋入連接函數, 空置一個Connection 等這些,如果非特別大的項目裏用的話,這個自己實現一些簡單的管理 不是很難的啊。
我到時覺得思路有了,自己實現應該可以的吧。
唯一的问题就是,连接数越多,启动越慢,因为要先创建在那儿,不过你可以修改为使用时创建也可以,
这样就可以避免启动时慢的问题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.
你的连接池没有做同步处理,在多线程使用时会出现问题。
帮LZ up!