多线程Delphi数据库应用程序因大量数据而失败

时间:2011-03-01 17:41:39

标签: mysql sql multithreading delphi

应用程序概述:
我有一个Delphi应用程序,允许用户定义多个查询,并在多个MySQL数据库上同时运行它们。可以一次运行的线程数量有限制(用户可以设置)。用户选择要运行的查询以及运行查询的系统。每个线程使用TADOQuery组件在指定的系统上运行指定的查询。

问题描述:
当查询检索到少量记录时,即使提交了大量线程(最多约100个),应用程序也能正常工作。只要一次只运行几个线程(最多约8个),应用程序也可以处理大量记录(150,000+)。但是,当用户一次运​​行超过10个查询(即10个以上的线程),并且每个线程正在检索大约150,000多条记录时,我们就开始收到错误。以下是我们到目前为止遇到的具体错误消息:

a:Not enough storage is available to complete this operation
b:OLE error 80040E05
c:Unspecified error
d:线程创建错误:Not enough storage is available to process this command
e:Object was open
f:ODBC Driver does not support the requested properties

显然,错误是由多种因素共同造成的:线程数,每个线程检索的数据量以及可能的MySQL服务器配置。

主要问题是为什么会出现错误?我很欣赏它似乎在某种程度上与资源有关,但鉴于返回的错误不同,我想了解错误出现的原因。例如,它取决于PC上的资源,或者与服务器的配置有关。

跟进问题是我们可以做些什么来避免出现问题?我们目前通过降低可以并发运行的线程数来限制应用程序。我们无法强制用户检索较少的记录,因为查询完全是用户定义的,如果他们想要检索200,000条记录,那么这取决于它们,因此我们无法做很多事情。实际上,我们不想降低应用程序的速度,因为大多数用户将检索少量数据,并且我们不希望使应用程序变慢以供他们使用,尽管线程数量可以由用户更改,我们宁愿找到问题的根源,并尝试修复它,而不必依赖于调整配置。

4 个答案:

答案 0 :(得分:5)

看起来你在客户端加载了很多数据。它们可能需要缓存在客户端内存中(特别是如果使用双向游标),并且在32位应用程序中可能不够,具体取决于平均行大小以及库存储行的效率。 通常,完成数据库工作的最佳方法是直接在服务器上执行该操作,而无需将数据检索到客户端。通常,数据库具有高效的缓存系统,并且当数据不适合内存时可以将数据写入磁盘。 为什么一次检索150000行?您可以使用一种机制仅在用户实际访问数据时传输数据(通过数据进行分页),以避免大量“浪费”的内存。

答案 1 :(得分:4)

这很有道理(事实上你遇到了问题,而不是具体的错误)。仔细考虑一下 - 您拥有相当于10个数据库连接(每个线程1个),每个连接在单个网络连接上接收150,000行数据(总共1,500,000行)。即使你没有使用客户端游标并且行很小(只有几个小列),这是一个巨大的数据流跨单个网络接口,并且客户端计算机上的内存受到很大影响。

我怀疑错误消息不正确,就像有时您在另一个代码位置内存覆盖造成访问冲突一样。

答案 2 :(得分:0)

根据您的DBMS,为了解决问题,您可以使用LIMIT / TOP sql子句来限制返回的数据量。

答案 3 :(得分:0)

我会做的事情:

  • 编写一个非常简单的测试应用程序,该应用程序仅使用连接/查询创建的必要部分(使用线程),这将消除由软件的其他部分引起的所有副作用

  • 使用不同的数据库访问层而不是ODBC,以查明ODBC驱动程序是否是问题的根本原因

  • 当线程数量很少时看起来内存使用没问题 - 为了验证这一点,我还会测量/计算记录的内存需求,将其与应用程序的内存使用情况进行比较操作系统。例如,如果测试显示四个线程可以安全地查询1.5 GB的总数据而没有问题,但是十个线程在总数据不足0.5 GB的情况下失败,我会说这是一个线程问题