Coldfusion 是否有解决此cfqueryparam内存泄漏的方法?

Coldfusion 是否有解决此cfqueryparam内存泄漏的方法?,coldfusion,cfqueryparam,Coldfusion,Cfqueryparam,更新: 我已经向Adobe提交了这个bug,并引用了这个问题 在发生问题的真实代码中,我决定删除cfqueryparam的使用。我现在使用一个自定义函数根据类型格式化参数。我将不得不处理安全性和速度方面的问题,但在当前负载下,它可以让特定进程正常工作 在将来,我计划将数据文件拉入数据库中的临时表中。然后,我将尽可能多地使用SQL对数据执行操作,并将数据传输到活动表,而不是依赖ColdFusion 在插入数据时,我遇到了使用cfqueryparam标记在查询上循环的问题。(我没有使用选择或更

更新:

  • 我已经向Adobe提交了这个bug,并引用了这个问题

  • 在发生问题的真实代码中,我决定删除cfqueryparam的使用。我现在使用一个自定义函数根据类型格式化参数。我将不得不处理安全性和速度方面的问题,但在当前负载下,它可以让特定进程正常工作

  • 在将来,我计划将数据文件拉入数据库中的临时表中。然后,我将尽可能多地使用SQL对数据执行操作,并将数据传输到活动表,而不是依赖ColdFusion


在插入数据时,我遇到了使用cfqueryparam标记在查询上循环的问题。(我没有使用选择或更新查询进行测试)。循环会逐渐占用更多的内存,直到请求完成后才会释放这些内存。但是,只有在函数中循环查询时才会出现问题

它似乎对所使用的cfqueryparam标记的数量非常敏感。在本例中,有15个值被插入,但在我的代码中,实际需要这样做,我插入了未知数量的值,这会使问题更加严重

下面是显示问题的代码。给它一个数据源名称(在MSSQL上测试),它将创建一个tmp表并插入记录,例如在函数中有或没有。内存使用情况在非功能循环之前、之后显示,然后在功能内循环之后显示。它还请求垃圾收集,并在输出内存信息之前等待10秒,以确保尽可能准确地显示信息

根据我在这个特定测试中的经验,函数内循环导致使用了超过200mb的内存。在我的现实世界中,它使用ColdFusion崩溃:-(


插入tmp([col1]、[col2]、[col3]、[col4]、[col5]、[col6]、[col7]、[col8]、[col9]、[col10]、[col11]、[col12]、[col13]、[col14]、[col15])
值(,,,,,,,)
插入tmp([col1]、[col2]、[col3]、[col4]、[col5]、[col6]、[col7]、[col8]、[col9]、[col10]、[col11]、[col12]、[col13]、[col14]、[col15])
值(,,,,,,,)
#参数标签#
使用的内存:#圆形(已存储)#mb
createObject(“java”,“java.lang.Runtime”).getRuntime().gc();
createObject(“java”、“java.lang.Thread”).sleep(arguments.waitSeconds*1000);
升降台
创建表tmp(
col1-nchar(10)NULL、col2-nchar(10)NULL、col3-nchar(10)NULL、col4-nchar(10)NULL、col5-nchar(10)NULL、col6-nchar(10)NULL、col7-nchar(10)NULL、col8-nchar(10)NULL、col9-nchar(10)NULL、col10-nchar(10)NULL、col11-nchar(10)NULL、col12-nchar(10)NULL、col13-nchar(10)NULL、col14-nchar(10)NULL、col15-nchar(10)NULL
)在[小学]
为了说明在操作期间可以释放内存,下面的示例代码构建了一个更大的结构,并显示了变量被覆盖和垃圾回收前后使用的内存。在我的运行中,填充后使用的内存为118mb,覆盖和垃圾回收后使用的内存为31mb

<cfset showMemory("Before struct creation")>
<cfflush interval="1">

<cfset tmpStruct = {}>
<cfloop from="1" to="1000000" index="i">
    <cfset tmpStruct["index:#i#"] = "testvalue testvalue testvalue testvalue testvalue testvalue testvalue testvalue testvalue testvalue">
</cfloop>

<cfset showMemory("After struct population")>
<cfflush interval="1">

<cfset tmpStruct = {}>
<cfset showMemory("After struct overwritten")>

您是否在Administrator中进行了调试

如果是这样的话,即使您得到了
showdebugoutput=“false”
,CF也会保留所有这些查询的调试信息,并且有这么多的查询,调试信息可能会很快积累起来



另外,如果您真的有80000行要插入,那么您可能希望以另一种方式执行此操作—例如,生成直接针对DB运行的导入脚本(而不需要CF/JDBC).

不知道这是否会产生影响,但需要尝试一些东西-收缩函数内循环,并多次循环函数

这对内存的作用可能有助于缩小内存的使用范围。


...
可能会有帮助吗?这种技术本身通常工作得更快,节省一些时间可以帮助您节省一些内存

是的,我看过你的笔记“插入未知数量的值”,但如果你在一个安装批中有恒定数量的字段/值,这应该会起作用。

尝试在你的CFFunction中的每个查询之前预先添加“变量”。我也遇到过类似的问题,这就解决了它

因此,改变:

<cfquery name="testq" datasource="CongressPlus">


干杯


Thomas

我的第一个猜测是在cfqueryparam中键入值-如type=“CF\u SQL\u CHAR”。这为什么会有帮助?我不确定,但我可以猜测,使用非类型变量会增加额外的开销。

社区中都有很好的记录,CF在请求完成之前不会释放内存。即使直接调用GC也不会在运行请求期间释放内存。不知道是否没有他的行为是故意的,或者是一个错误

我不知道你为什么想在CF中做这样的事情。你没有理由使用CF在数据库中插入80K行,不管你使用的是哪个数据库引擎

现在,如果您需要这样做的原因是什么,比如从上传的CSV或XML文件中获取数据,那么MSSQL有很多更好的方法和解决方法

我多年来所做的一种方法是在MSSQL中创建一个存储过程,调用或读取包含要插入的数据的文件

这种方法最好的一点是CF所做的唯一一件事就是处理文件上传,MMSQL正在处理文件的所有工作
<cffunction name="funcTest" output="false">
    <cfargument name="from" />
    <cfargument name="to" />
    <cfset var i = 0>
    <cfset var testq = "">
    <cfloop from="#arguments.from#" to="#arguments.to#" index="i">
        <cfquery name="testq" datasource="#dsn#">
            ...
        </cfquery>
    </cfloop>
</cffunction>


<cfset BlockSize = 100 />
<cfloop index="CurBlock" from="1" to="#(InsertCount/BlockSize)#">

    <cfset funcTest
        ( from : CurBlock*(BlockSize-1) + 1
        , to   : CurBlock*BlockSize
        )/>

</cfloop>
<cfquery name="testq" datasource="CongressPlus">
<cfquery name="variables.testq" datasource="CongressPlus">
<cfloop from="1" to="#insertCount#" index="i">
    <cfquery name="testq" datasource="#dsn#">
        ...
    </cfquery>
</cfloop>
<cfquery name="testq" datasource="#dsn#">
    <cfloop from="1" to="#insertCount#" index="i">
        ...
    </cfloop>
</cfquery>