Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/277.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何减少C#程序中Sql连接池使用的内存量_C#_Sql Server 2008_Out Of Memory - Fatal编程技术网

如何减少C#程序中Sql连接池使用的内存量

如何减少C#程序中Sql连接池使用的内存量,c#,sql-server-2008,out-of-memory,C#,Sql Server 2008,Out Of Memory,我有一个C#程序,它充当多线程web服务器。它对Sql Server数据库中的Xml结构进行大量处理 随着这些Xml结构的增加,我发现应用程序的内存不足 我已经部署了ANTS内存分析器来查看正在发生的事情,并设法减少了处理过程中内存中保留的大字符串的数量,并对事情做了一些改进 然而,我现在只剩下一个碎片化的大对象堆,这是由连接池中的大字节数组造成的。大字节数组是 TdsParserStateObject._bTmp in TdsParser._physicalStateObj in SqlInt

我有一个C#程序,它充当多线程web服务器。它对Sql Server数据库中的Xml结构进行大量处理

随着这些Xml结构的增加,我发现应用程序的内存不足

我已经部署了ANTS内存分析器来查看正在发生的事情,并设法减少了处理过程中内存中保留的大字符串的数量,并对事情做了一些改进

然而,我现在只剩下一个碎片化的大对象堆,这是由连接池中的大字节数组造成的。大字节数组是

TdsParserStateObject._bTmp
in TdsParser._physicalStateObj
in SqlInternalConnectionIds._parser
in DbConnectionInternal[0]
in DbConnectionPool._objectList
我99.9%确定我只在using语句中使用了连接,尽管我在线程运行时每个线程都保持一个连接打开(这是为了优化,但我怀疑这是否会让事情变得更糟)

我可以对连接做些什么来减少它所拥有的内存量(除了关闭或处理它)

还是每次使用时都要立即关闭或处理所有连接

[稍后-根据我的评论] 我重构了代码,为每个数据库访问使用一个新连接,然后将其处理掉(当然,除了事务,在事务中,我从事务开始到结束使用相同的连接,并将其与事务一起处理)

即使程序处于空闲状态(即未使用任何连接),连接池中仍有连接占用大量内存,并导致碎片

为什么已处理的连接在连接池中会保留58MB的内存

[更晚] 我有一个解决方案可以防止Sql Server连接池对大型堆进行碎片化—这是检测哪些连接可能具有巨大的缓冲区,并使用

SqlConnection.ClearPool(连接)

我现在用一种相当粗糙的方式来做这件事,通过对DataReader进行子类化,并检测返回的字段是否超过10MB

欢迎提供关于检测哪些连接具有大缓冲区的更好方法的建议

请注意,我已经恢复了在每次数据库访问时打开和处理连接的更改,因为在事务内部跟踪要使用的连接(显然必须是事务连接)让我头痛不已


在线程开始时打开并在线程结束时关闭的连接是正常的,因为几乎所有线程都是短期的(是对单个web请求的响应)。例外情况是可能在单个事务上下文中运行的批处理过程。

使用ADO.NET时,无需保持连接打开。默认情况下,连接将被池化(除非您自己关闭了池化),ADO.NET将完成池的所有管理。您甚至不必担心不同的用户凭据等,因为只有在连接参数相同的情况下,连接才会被池化。从内存使用的角度来看,处理连接只会有所帮助

关于这方面的更多信息:

  • 在MSND上

在某种程度上,西蒙的答案是好的,所以我投了赞成票

然而,他的回答并没有解决许多问题。每当通过SqlConnection检索到非常大的数据(在我的例子中,一个包含大约10MB Xml的文本字段)时,连接的内部缓冲区似乎变得非常大

如果您有一个同时使用多个连接的程序,并且具有大数据,那么在您处理了所涉及的SqlConnection之后,这些大缓冲区仍会被连接池引用,这会导致大数据堆的碎片化

我发现防止这种情况的唯一方法是检测用于大数据的SqlConnections,并在处理它们之前将其从连接池中删除


从我问题后面的编辑中可以看出,我没有找到一种优雅的方法来检测SqlConnection内部缓冲区是否大,只是一个非常不雅的缓冲区,方法是对DataReader进行子类化,并检测返回的字段是否超过10MB

Ado.net没有连接池,您不必保持连接打开。请参阅Try,在线程运行时不要保持每个线程一个连接处于打开状态,并注意内存消耗的差异,这样您就可以知道这是否是最重要的因素。连接池应该可以减少每个线程保持连接的需要,除非您对某些线程使用不同的凭据。这是为了优化,但我怀疑这是否会让事情变得更糟。我想有一句话是这样说的,我重构了代码,为每个数据库访问使用一个新连接,然后将其处理掉(当然,除了事务,在事务中,我从事务开始到结束使用相同的连接,并将其与事务一起处理)。即使程序处于空闲状态(即未使用任何连接),连接池中仍有连接占用大量内存。我发现阻止Sql Server连接分割大型堆的唯一方法是从连接池中删除可能具有大型缓冲区的连接。请参阅问题编辑。我还需要添加对写入大量数据的连接的检测。