【问题标题】:How to refresh individual query cache in ColdFusion 2016如何在 ColdFusion 2016 中刷新单个查询缓存
【发布时间】:2017-11-30 21:07:02
【问题描述】:

我发现一段代码可以在 ColdFusion 10 引擎下运行,但不能在 ColdFusion 2016 (CF12) 引擎下运行。

我有一个 CFC,其中包含由函数调用获取的缓存查询。假设我有一个要缓存的查询,但我对该查询使用的 db 表进行了更改。我没有看到返回的缓存查询中的数据,所以我需要刷新查询缓存,很简单。这就是我设置代码的方式:

<cffunction name="getVariables" access="public" returntype="query">
    <cfargument name="time_span" required="true" default="#this.cacheSpan#" />
    <cfset var qryGetVariables="">

    <!--- IF REFRESH, NEW QRYTIMESPAN --->
    <cfif arguments.time_span eq 0 AND NOT this.bln_refresh>
        <!--- IF time_span 0 but not refresh, reset to original cache span --->
        <cfset arguments.time_span = this.cacheSpan />
    </cfif>
    <cfquery name="qryGetVariables" datasource="#this.dsn#" cachedwithin="#arguments.time_span#">
        select *
          from get_variables
         order by id, value
    </cfquery>
    <cfreturn qryGetVariables>
</cffunction>

我在同一个 CFC 中调用一个函数,该函数以下列方式刷新此查询:

this.bln_refresh = true;
<cfinvoke method="getVariables" returnvariable="qryReturn">
   <cfinvokeargument name="time_span" value="0" />
</cfinvoke>
this.bln_refresh = false;

同样,这之前在 ColdFusion 10 上有效,但现在在 ColdFusion 2016 上无效。我需要做些什么不同的事情来刷新此特定查询的缓存?

【问题讨论】:

  • 我不使用 2016 版,但缺少参数类型可能是相关的。顺便问一下,does not work 是什么意思?
  • 我的意思是当我刷新 cachedwithin timespan 变量时,它应该刷新缓存的查询以使用我在数据库中添加的新值来更新它。 “不起作用”意味着当我通过 CFC 方法进行刷新时,通过为时间跨度传递 0 的参数,缓存的查询不会被刷新。它仍然显示旧值而不是新值,这在 CF10 之前有效。
  • @user1100412 很高兴您找到了解决方案。不要在您的问题中包含解决方案,而是将其添加为该问题的新答案并接受它。可以在这里回答您自己的问题。就像你所做的那样给予适当的信任。干杯。

标签: caching coldfusion refresh query-cache coldfusion-2016


【解决方案1】:

是的,这在 CF10 之后发生了变化。 It's considered as bug, but it still not fixed. 查询结果一旦使用cachedWithin 缓存后,就不能使用createTimeSpan(0, 0, 0, 0)(等于0)或任何负值使其失效。

演示

<!--- cache data for 10 minutes --->
<cfquery cachedWithin="#createTimeSpan(0, 0, 10, 0)#">
    SELECT `foo` FROM `example`;
</cfquery>

|富
|-----
| ABC

让我们更改数据。

UPDATE `example` SET `foo` = 'DEF';

正如预期的那样......

<!--- invalidate cache and fetch new data --->
<cfquery cachedWithin="#createTimeSpan(0, 0, 0, 0)#">
    SELECT `foo` FROM `example`;
</cfquery>

|富
|-----
|防御

现在让我们缓存最新的数据。

<!--- cache new data for 10 minutes --->
<cfquery cachedWithin="#createTimeSpan(0, 0, 10, 0)#">
    SELECT `foo` FROM `example`;
</cfquery>

CF10 中的结果

|富
|-----
|防御

cachedWithin &lt;= 0 使缓存查询无效。因此下一个cachedWithin &gt; 0 将新数据存储在缓存中。

CF2016 结果

|富
|-----
| ABC

cachedWithin &lt;= 0 只是跳过了缓存。下一个 cachedWithin &gt; 0 从缓存中获取。并且缓存没有改变。


更新

当前解决此错误的方法是使用&lt;cfquery&gt;cacheID 属性,然后使用cacheRemove(theCacheID) 使其无效。

旧答案

您可以使用&lt;cfobjectcache action="CLEAR"&gt; 使查询缓存无效,但是它会使所有缓存的查询无效,这很糟糕。另一种选择是使用cachePut 自己缓存查询并使用cacheGet 获取它。

这里是如何做的提示。您可能必须在此处合并您的 this.cacheSpan 逻辑,我不确定它的目标是什么:

<cffunction name="getVariables" access="public" returntype="query">

    <cfargument name="time_span" required="true" default="#this.cacheSpan#">

    <cfset var qryGetVariables = "">

    <cfset var cacheKey = "qryGetVariables"> <!--- make sure the key is unique and only used in this function --->
    <cfset var useCache = ((arguments.time_span lte 0) or this.bln_refresh)>

    <cfif useCache>
        <cfset qryGetVariables = cacheGet(cacheKey)>
    </cfif>

    <cfif not isQuery(qryGetVariables)>

        <cfquery name="qryGetVariables" datasource="#this.dsn#">
            select *
              from get_variables
             order by id, value
        </cfquery>

        <cfset cachePut(cacheKey, qryGetVariables, arguments.time_span)>

    </cfif>

    <cfreturn qryGetVariables>
</cffunction>

【讨论】:

  • Adobe 是否在任何地方发现了这种变化? (对于我编写的所有应用程序来说,这是一个相当大的问题,看起来需要大量额外的工作才能使特定的缓存查询无效或清除。)
  • @JamesMoberg 这是一个需要修复的确认错误:tracker.adobe.com/#/view/CF-4198513
  • 谢谢。我正在向查询动态添加一个带值的列。随后的重新查询返回修改后的查询而不是初始缓存的查询。 gist.github.com/JamoCA/fe7ff5be43560ba6f8b6c513fdf9f723(这可能不是同一个错误,但同样严重。)
【解决方案2】:

非常感谢@Alex,我遇到了以下似乎可以在我们的服务器上运行的解决方案:

<cffunction name="getVariables" access="public" returntype="query">
    <cfargument name="time_span" required="true" default="#this.cacheSpan#" />
    <cfset var qryGetVariables="" />
    <cfset var flt_qryTimeSpan=0>

    <cfif NOT cacheIdExists("qryGetVariablesCache") OR this.bln_refresh>
        <cfquery name="qryGetVariables" datasource="#this.dsn#" cachedwithin="#flt_qryTimeSpan#">
            select *
              from get_variables
             order by id, value
        </cfquery>
        <cfset cacheRemove("qryGetVariablesCache") />
        <cfset cachePut("qryGetVariablesCache",qryGetVariables,this.cacheSpan) />
    <cfelse>
        <cfset qryGetVariables = cacheGet("qryGetVariablesCache") />
    </cfif>
    <cfreturn qryGetVariables>

</cffunction>

【讨论】:

    【解决方案3】:

    我不知道@Alex 所说的是否正确,但我没有理由怀疑他。我没有运行 ColdFusion 2016。也许这是为特定查询刷新缓存的另一个选项...

    请记住,当使用cfquery 标记的cachedWithin 属性时,它只会在满足以下所有条件时缓存查询。 "只有在Administrator中开启查询缓存才生效。要使用缓存数据,当前查询必须使用相同的SQL语句、数据源、查询名、用户名和密码。" (@ 987654321@)

    专注于这部分 - 相同的 SQL 语句。如果稍微更改 SQL 语句,缓存将被刷新。所以也许你可以在你的 SQL 语句中添加另一个条件来刷新查询。您甚至可以使用您已经拥有的相同变量time_span

    我在想这样的事情(语法可能因您的 DBMS 而异):

    <cfquery name="qryGetVariables" datasource="#this.dsn#" cachedwithin="#arguments.time_span#">
        select *
        from get_variables
        where '#arguments.time_span#' = '#arguments.time_span#'
        order by id, value
    </cfquery>
    

    条件应始终为真,因此查询将返回相同的结果集。

    *我没有测试过这个。

    【讨论】:

    • 我已经通过 Slack 向 CF 团队报告了一个类似的问题,这个问题甚至比这个 cachedWithin 错误更严重。 CF 团队正在“进一步评估”以确定如何修复它。我的问题是关于后续查询实际上没有返回并从缓存中刷新查询变量。 gist.github.com/JamoCA/fe7ff5be43560ba6f8b6c513fdf9f723(在修复此问题之前,我无法从 CF9/10 升级。)
    猜你喜欢
    • 1970-01-01
    • 2013-02-15
    • 2023-03-23
    • 2016-05-18
    • 1970-01-01
    • 2017-04-29
    • 1970-01-01
    • 1970-01-01
    • 2021-10-02
    相关资源
    最近更新 更多