如何在 ColdFusion 2016 中刷新单个查询缓存
How to refresh individual query cache in ColdFusion 2016
我发现一段代码在 ColdFusion 10 引擎下运行,但在 ColdFusion 2016 (CF12) 引擎下不运行。
我有一个 CFC,其中包含由函数调用获取的缓存查询。假设我有一个要缓存的查询,但我对该查询使用的数据库 table 进行了更改。我没有在返回的缓存查询中看到数据,所以我需要刷新查询缓存,很简单。这就是我设置代码的方式:
<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 上无效。我需要做些什么来刷新这个特定查询的缓存?
是的,这在 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>
|富
|-----
|美国广播公司
让我们更改数据。
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 <= 0
使缓存的查询无效。因此下一个 cachedWithin > 0
将新数据存储在缓存中。
CF2016成绩
|富
|-----
|美国广播公司
cachedWithin <= 0
只是跳过了缓存。接下来的 cachedWithin > 0
从缓存中获取。并且缓存没有改变。
更新
此错误的当前解决方法是使用 <cfquery>
的 cacheID
属性,然后使用 cacheRemove(theCacheID)
.
使其无效
旧答案
您可以使用 <cfobjectcache action="CLEAR">
、 使查询缓存无效,但是 它会使所有缓存的查询无效,这非常糟糕。另一种选择是使用 cachePut
and fetching it using 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>
我不知道@Alex说的对不对,但我没有理由怀疑他。我不是 运行 ColdFusion 2016。也许这是为特定查询刷新缓存的另一种选择...
请记住,当使用 cfquery
标记的 cachedWithin
属性时,它只会在满足以下所有条件时才缓存查询。 "只有在 Administrator 中启用查询缓存时才会生效。要使用缓存数据,当前查询必须使用相同的 SQL 语句、数据源、查询名称、用户名和密码。" (cfquery documentation)
关注这部分 - 相同的 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>
条件应始终为真,因此查询将 return 相同的结果集。
*我没有测试过这个。
非常感谢 @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>
我发现一段代码在 ColdFusion 10 引擎下运行,但在 ColdFusion 2016 (CF12) 引擎下不运行。
我有一个 CFC,其中包含由函数调用获取的缓存查询。假设我有一个要缓存的查询,但我对该查询使用的数据库 table 进行了更改。我没有在返回的缓存查询中看到数据,所以我需要刷新查询缓存,很简单。这就是我设置代码的方式:
<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 上无效。我需要做些什么来刷新这个特定查询的缓存?
是的,这在 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>
|富
|-----
|美国广播公司
让我们更改数据。
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 <= 0
使缓存的查询无效。因此下一个 cachedWithin > 0
将新数据存储在缓存中。
CF2016成绩
|富
|-----
|美国广播公司
cachedWithin <= 0
只是跳过了缓存。接下来的 cachedWithin > 0
从缓存中获取。并且缓存没有改变。
更新
此错误的当前解决方法是使用 <cfquery>
的 cacheID
属性,然后使用 cacheRemove(theCacheID)
.
旧答案
您可以使用 <cfobjectcache action="CLEAR">
、 使查询缓存无效,但是 它会使所有缓存的查询无效,这非常糟糕。另一种选择是使用 cachePut
and fetching it using 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>
我不知道@Alex说的对不对,但我没有理由怀疑他。我不是 运行 ColdFusion 2016。也许这是为特定查询刷新缓存的另一种选择...
请记住,当使用 cfquery
标记的 cachedWithin
属性时,它只会在满足以下所有条件时才缓存查询。 "只有在 Administrator 中启用查询缓存时才会生效。要使用缓存数据,当前查询必须使用相同的 SQL 语句、数据源、查询名称、用户名和密码。" (cfquery documentation)
关注这部分 - 相同的 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>
条件应始终为真,因此查询将 return 相同的结果集。
*我没有测试过这个。
非常感谢 @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>