ADO的并行处理能力是否很弱?在线程中使用ADO并行查询经常出错,请教。 (200分)

  • 主题发起人 主题发起人 dirk
  • 开始时间 开始时间
D

dirk

Unregistered / Unconfirmed
GUEST, unregistred user!
需要查询一个比较大的列表,把这个查询放到一个线程中执行,多个线程之间并没有关系,独自完成各自的查询,当多个线程并行执行时,经常出错,非常不稳定,几乎就是只要有两个线程在执行就出错。
1、各线程中使用的TADOQuery是各线程的私有变量,在线程中创建、释放,各线程只公用一个TADOConnection,在查询过程中,没有其他用户对数据库进行更新操作,没有锁的问题。
2、使用一个OpenSQL过程打开记录集。
3、数据库如果是Oracle,返回的错误是:“对象被打开。”,数据库如果SQLServer,返回错误:“连接占线导致另一个命令”。
4、代码是写在dll中的,TADOConnection是做为参数传过去的,各线程公用。
有人说要CoInitialize,这个没用,实际上,CoInitialize在dll调用时已经用过了,参考了连红星的“大富翁论坛离线浏览器2.1.3.449”源码,发现,把TADOQuery的游标设成服务器端出错的概率要小很多:FQuery.CursorLocation:=clUseServer;,但仍时不时的会出错,只是不像使用客户端游标那样一运行就出错(TADOQuery默认是客户端游标)。
我把相关代码简化,放在小雨哥的网站上,请下载运行一下看看 http://ale.xicp.net/upload/ThreadADOTest.rar ,其中测试了各种情况,TMy1Thread使用的都是默认的设置,数据库是Oracle情况好些,SQLServer2000次之,SQLServer7狂出错。
今天试了在线程中创建TADOConnection,即每个线程用一个TADOConnection,呵呵,TMy1Thread就不出错,开50个线程测试,就是慢多了(ThreadADOTest.rar是几天前上传的,没有这部分代码)。
从出错的提示看,感觉是ADO的并行处理方面的问题,好像这ADO方面能力比较弱,BDE中使用多线程要使用TSesson,但ADO中没有TSesson,怎么办?
谁能帮我解了这个麻烦?
 
AdoDataSet 默认使用自己的线程连接数据库.而DELPHI BDE使用 SESSION 的目的是为了节约SERVER上的连接数, 使用TDATABASE和TSESSION可以使多个TQUERY通过一个数据管道连接到SERVER, 这对SERVER是很有好处的ADODATASET 默认自己使用自己的SESSION,其连接SERVER是发生在COM层面上,所以它不需要SESSION, 但是要安全的使用多线程ADO, 应该每个线程都使用自己的ADO组件访问。
 
>>但是要安全的使用多线程ADO, 应该每个线程都使用自己的ADO组件访问
意思是否是每个线程都要用单独的TADOConnection?
从现在的情况看每个线程使用了自己的TADOConnection,不与可能发生并行执行的线程共用一个TADOConnection就不出错,反之就出错,另外这个出错提示,看起来是ADO的错误提示,而不是数据库返回的错误异常,能给解释一下这个错误到底是什么意思吗?
 
>>但是要安全的使用多线程ADO, 应该每个线程都使用自己的ADO组件访问
如何做?TADOQuery是否是“自己的ADO组件”?还是指的是TADOConnection?
 
不好意思,我这里没有环境,你能错误上贴上来吗?
 
ADO是safe的(按微软说法 ),但每个Connection任何时候只能处理一个事务,请查DBMS有关资料。所以,最好每个线程管理一个连接,如果共享Connection,程序比较复杂。
 
上面已经贴出了错误:
3、数据库如果是Oracle,返回的错误是:“对象被打开。”,数据库如果SQLServer,返回错误:“连接占线导致另一个命令”。
就是这样的,而且是中文,应该是ADO返回的错误,而不是数据库。
 
另外, http://www.delphibbs.com/delphibbs/dispq.asp?lid=2520514 的问题可能也是一样的。
 
程序中没有用到事物。
 
用ADO多线程没问题,一个TADOConnection共享足够了。
ADO数据访问组件必须在各线程中创建,
你的问题可能出在Thread中的所有对控件的操作要用 Synchronize
同步一下。
最后别忘了 CoInitialize(nil);
CoUninitialize;
每个线程用一个TADOConnection当然也可以解决问题,但是
好像不太专业。
另外,我的qq 537636,msn dj7911@hotmail.com
我可能有些fb/ib的问题请教
 
我前面说了,CoInitialize(nil);
CoUninitialize没有用,另外我的线程中不需要用Synchronize ,因为没有涉及到线程外的对象,请下载 http://ale.xicp.net/upload/ThreadADOTest.rar 看一下,代码很短,一分钟就看明白了,然后在SQLServer7上用TMy1Thread测试一下,就可以看到问题了,如果有Oracle、SQLServer2000测试就更好了,可以看到“对象被打开。”错误,而使用了clUseServer的线程出错的情况要少的多。
奇怪。
 
你把:ADOConnection.Mode改为cmShareDenyNone试试。
 
我这里写出来的东西都是这几天的测试结果,在公司三台机器上都可重复,请各位也测试一下,看看是否出一样的错。
 
不好意思我正在外面出差,现在没有环境调试。
 
http://www.csdn.net/develop/article/15/15537.shtm
csdn上找到的,不知道这家伙说的对不对。
我机器上没有任何大型数据库了。
 
再看看http://www.delphibbs.com/delphibbs/DispQ.asp?LID=389081
看来还要另想办法才行
 
好文章,看来可以解决你的问题。
 
下载不了,[:(]
 
我刚解决了这个同类问题(http://www.delphibbs.com/delphibbs/dispq.asp?lid=2520514),确实使用Synchronize就可以了。
 
嗯,现在才上来,多谢了,我想我知道了,大致和我设想的差不多,明天再好好整理一下,晚安,各位,呵呵呵
 
后退
顶部