BDE多线程所遇到的内存不足问题(100分)

  • 主题发起人 cocochuong
  • 开始时间
C

cocochuong

Unregistered / Unconfirmed
GUEST, unregistred user!
我自己写了一个访问数据库的类,由于是在线程中执行,所以根据BDE的要求,每
个线程中访问数据库时必须用一个唯一的Session。
可这样就出现了一个问题,这个类在我的win2000上最多只能存在12个实例,多于
12个时就会出现:Insufficient memory for this operation.这个错误。逐步跟
踪错误来源,发现是第13次执行Fdatabase.connected:=true时出现这个错误,此
时应该是BDE的内存不够而引起的,请问有什么办法解决呢?能不能扩大BDE 使用
的内存或者有什么其它的办法呢?
后来我换了一台机器再试,发现该类实例多于8个时就出现同样错误,可该机器是
192M内存的呀。
类为:Tthquery
成员:
FSession:TSession;
FDatabase:TDatabase;
qry1,qry2,qry3:TQuery;
Prepared:Boolean;
constructor Create;
destructor Destroy;override;
procedure Free;
构造函数:
FSession:=TSession.Create(nil);
FDatabase:=TDatabase.Create(nil);
qry1:=TQuery.Create(nil);
qry2:=TQuery.Create(nil);
qry3:=TQuery.Create(nil);
FSession.AutoSessionName :=true;
with FDatabasedo

begin

FSession.Open;
Connected:=false;
Params.Clear;
LoginPrompt:=false;
SessionName:=FSession.SessionName ;
DatabaseName:=FSession.SessionName ;
DriverName:=glDriverName;
Params.Values['SERVER NAME']:=glServerName;
Params.Values['DATABASE NAME']:=glDbName;
Params.Values['USER NAME']:=glUserName;
Params.Values['PASSWORD']:=glPassword;
Connected:=true;
qry1.SessionName:=FSession.SessionName;
qry1.DatabaseName:=FDatabase.DatabaseName;
qry2.SessionName:=FSession.SessionName;
qry2.DatabaseName:=FDatabase.DatabaseName;
qry3.SessionName:=FSession.SessionName;
qry3.DatabaseName:=FDatabase.DatabaseName;
Prepared:=true;
end;

 
我試了一下﹐一運行就有訪問沖突
洗耳工聽
 
其实这是BDE的缺陷,BDE的SESSION并不是并发的,你想在WINDOWS下的基于MESSAGE的编程能实现多SESSION并发吗?
所以当SESSION多的时候就会冲突。
建议你用ADO试试,它对多SESSION解决的比较好。
 
这就对了,你要是不出问题,才怪了。我的都出问题了,你的能不出问题么?
解决办法,打开BDE Administrator,在configure那一页,system/init/
有一些配置,你把那些数字都加大N倍就可以了,至于多少,等下一次出问题的时候,
再加大就可以了。其实,有用的只有一项,具体我也忘了,很久以前发现的,反正现在我
是每一项增大N倍。
我做的多线程,没一台机器开80个,就是80个Session.
 
多线程里用ODBC的或者ADO比较好,BDE经常出问题。
 
BDE最多只能带100多台了
 
cocochuong,你好象没有设置SessionName,而是AutoSessionName:=true,
好象有点问题,我倒没试过这么做。
你在一个Form上放两个Session,然后试图让其中一个AutoSessionName为True,
看看有什么出现。
 
cocochuong:你发的问题我已经收到,非常不好意思现在才答复你.
以下是我的一些个人看法,不一定正确,忘大家指教
1.onedolph的方法勉强可以行得通,但非常不好.主要是受到机器的性能和BDE自己本身的
限制.
2.ADO更是不可取.ADO本身是不能在多线程程序中使用的.如果大家侥幸在多线程中使用
了,没出什么大问题,但并不代表它能在多线程中使用.这是由于ADO本身的机制导致的。
具体为什么,我也不是很清楚.在很多书籍里都介绍过,不能在多线程中使用它.
3.照以上讲来,好象就没办法了。其实不然.我们仔细想一想,在实际数据库中,不也有并发
操作受到限制的情况吗.但实际上我们平时进行多个连接会话,好象也没感到区别 .其实
这是数据库本身进行了排队管理.因此,我们也可以借鉴数据库本身的管理机制,对会话
进行排队管理 .现将简单的算法列出。
A:可以根据程序的需要,对会话数进行定义.如n=10左右(根据系统和应用程序的需要而定)
B: 预先开设n个数据操作线程(或动态开设n个----不推荐这么做,难于管理)和一个线程
管理队列.
C:设计一个数据请求操作队列(全局变量),其中包括出列,入列操作.
D:每个数据操作线程循环的扫描数据请求操作队列,如有请求,则将请求出列,然后,进行
相应的数据操作.
E:在以上操作中,最重要要注意的是对队列操作的同步.无论是出列还是入列.
根据以上的改进,可以大大提高数据访问的效率,和同时(假象)连接的数量.
抛砖引玉,希望大家多多探讨.


 
啊,碰见高手了。
gben所言极是。
当然了,我们用的机器是非常好的,IBM的工控,512M内存,PIII500的芯片,那还用说,
人家给的钱多,当然不能用赛杨336来糊弄人家了。其实,80个线程还不是最多的,最多
的一台,开的是144个线程,当然,服务器就不用说了,开了500个连接(Oracle),那是1.5G
的内存!
要想马跑的快,就得让马吃好草!。
想问gben一个问题,>>Insufficient memory for this operation怎么解决?
想必gben同志肯定做过,而且是如上面所说的做的,真是:great mind thinks alike.
我也是这么做的。
说说我做的吧:
我们做的项目考虑到有的地方用户群比较多,比如四川,那是100万的用户量,西藏才不到
4万,宁夏也就15万左右。所以我考虑的是线程数可设的,把它放在.ini文件了,起的时候,
根据设设置来起。
我们做的时候,专门用一个程序来与数据库连接,其他程序如果有与数据库操作的话,都是
与该程序打交道,由它去执行,然后把结果返回。但并不是所有的线程都在一个程序里,
每个程序最大可开15个线程,一般我们都设为12,也就是说,上面的144个线程是起了12个
程序的。我们把这个东西称为数据库插件,用WinSocket来通讯。考虑到有不同的
数据库操作select,insert,update,执行存储过程,等,请求的时候,根据请求的不同,
发往不同的插件,这样,如果万一某种操作出了问题,要死也只是某一个程序死,
其他的还可以正常运行。另外,如果忙的时候,可以多开几个插件,不忙的时候,可以关掉
几个。这样就很灵活了。
还有一点,cocochuong,你不要一建起来你就让connected:=true;
其实,根本用不着,等有数据请求的时候,你样Query.Open,或者Query.ExecSQL,
数据库自然会连上去的。这样的话,有一点不好,第一次连接的时候,比较慢,但一旦连上去,
下次在有请求的时候,就快了。它的好处是,比如,开了10个线程,但这时请求比较少,
你的管理线程排队的时候下点工夫,每次从头找一个空的线程来执行,这样有可能只有前几个
线程被命中,那后几个线程根本没连上去,那对数据库的连接也只有几个。只有十个线程
都用完了,使个数据库连接才都会连上。实际上,据我的观察,在我们的系统中,一般开几个
线程,就有几个连接,肯定会用完的。因为第一次连接是比较慢的,可能有几秒钟,在这几秒内
接收到的请求已经超过了所开的线程数,还会有等待的,所以肯定用完的。那你看看你的系统
的需求了。
大家继续。
 
多人接受答案了。
 
顶部