【问题标题】:code is been executed twice coldfusion代码被执行了两次coldfusion
【发布时间】:2013-11-25 11:14:25
【问题描述】:

我有一个在 CF 任务中安排为每 30 秒运行一次的 ColdFusion 文件。此文件的目的是将响应表中的文本插入到订单表中。以前一切都很好,但现在有问题,即

随机 6 次中的 1 次,文件被执行两次,每行代码运行两次。所以订单被插入了两次。

我已检查是否存在具有响应 id xxx 的相同订单,请不要再次插入。但我仍然看到重复。任何帮助将不胜感激。

<cfquery name="getdupeordersinfile" datasource="#Application.ds#" dbtype="ODBC" username="#Application.UserName#" password="#Application.Password#">
        SELECT TOP 1 * from Orders
        Where ltrim(rtrim(smsresponseid)) = '#val(responseId)#'
    </cfquery>

    <cfif getdupeordersinfile.recordcount EQ 0>

        <cfquery name="getInsertInOrder" maxrows="1" datasource="#Application.ds#" dbtype="ODBC" username="#Application.UserName#" password="#Application.Password#" result="stResult">
            INSERT INTO Orders
               (....)
            values (...)

         </cfquery>


     </cfif>

谢谢

【问题讨论】:

  • 我会将这块 CFQUERIES 包装在 中,看看是否有帮助。此外,如果您添加列限制以禁止重复 SMSResponseID,则无论如何第二次插入都会失败。
  • 你确定它运行了两次吗? http 日志将帮助您确定这一点。另外,如果您需要每 30 秒运行一次,您是否考虑过使用数据库触发器而不是 CF?
  • 鉴于提供的信息有限,没有明显的原因代码会执行两次。您需要为我们提供更多背景信息。例如,脚本中的实际代码是什么(不仅仅是 sn-p)? responseId的来源是什么?是否涉及任何 CFC?此外,发布确认代码实际执行两次的日志记录结果。

标签: coldfusion


【解决方案1】:

我将使用以下查询的一些变体,它应该适用于任何现代 SQL 数据库:

INSERT INTO Orders
    (column1, column2, column3)
SELECT  column1, column2, column3
FROM    Responses
WHERE   1 = 1
    AND ...
    AND NOT EXISTS (
            SELECT  1
            FROM    Orders
            WHERE   ltrim(rtrim(smsresponseid)) = ltrim(rtrim(Responses.responseid))
        )

如果您输入的不是来自数据库的静态值,您也可以使用相同的技术。

INSERT INTO Orders
    (
        color,
        column1,
        column2
    )
SELECT  'red',
        <cfqueryparam value="#value1# ...>,
        <cfqueryparam value="#value2# ...>
WHERE   1 = 1
    AND NOT EXISTS (
            SELECT  1
            FROM    Orders
            WHERE   ltrim(rtrim(smsresponseid)) = ltrim(rtrim(Responses.responseid))
        )

我使用“SELECT 1”而不是“SELECT TOP 1”,因为您根本不需要获取任何字段。 "SELECT 1" 将只返回 1 的字面值。当然,这是没有用的,但无论如何您都不需要 EXISTS 子句中的实际值。此外,数据库无论如何都不会费心在 EXISTS 子句中检索多个记录。

SQL Server: JOIN vs IN vs EXISTS - the logical difference

这篇文章专门针对 SQL Server,但我的经验表明大多数 SQL 数据库都是如此。

EXISTS 和 NOT EXISTS 是此类问题的最佳解决方案,因为它会影响性能,而且语法正确且清晰地描述了您想要的内容。

为什么会这样?

正如我之前没有提到的,这就是代码可能执行两次的原因(只是推测,但我已经看到了)。

假设这段代码在 order-response.cfm 中。想象一下 order-response.cfm 被调用(由用户调用,由 CFSCHEDULE 调用,无关紧要)。将此请求称为 #1。紧接着,它再次被调用。调用此请求 #2。

在请求 #1 中,检查查询运行并且不返回任何记录。然后(在请求 #1 中完成插入查询之前),检查查询在请求 #2 中运行。现在,请求 #2 中的检查查询也没有返回任何结果。然后插入查询在请求 #1 中运行。然后插入查询在请求 #2 中运行(因为检查查询在运行时没有返回任何结果)。

这些请求必须彼此接近多少才能达到这种效果,这取决于您的代码运行速度,而这又取决于(某种程度上)您的服务器所承受的负载。如果您有一段时间数据库服务器被锁定(或相关表被锁定),那么您可能需要等待解锁,这可能会使这些步骤花费的时间比您预期的要长。

鉴于您的任务每 30 秒运行一次,您的数据库或 ColdFusion 的轻微减速可能会导致这些请求重叠,从而产生此问题。

将所有内容放在一个 SQL 语句中,使操作有点原子化,并且不太可能遇到这种情况(尽管在极少数情况下仍会发生)。

我应该提到(正如我认为其他人已经做过的那样),你应该在你的表中添加约束,以拒绝重复条目,以防万一通过该级别。

【讨论】:

  • 谢谢史蒂夫。但是代码会被执行两次是否有原因。
  • 是的,抱歉我忘了提。
【解决方案2】:

从响应表到你说的订单表。我的方法类似于:

insert into orders
(field1, field2, etc)
select field1, field2, etc
from response
where whatever
and somefield in
(select somefield 
from response
where -- here you specify the same conditions of the outer query
except
select somefield
from orders
)

确切的语法将取决于您的 rdbms。有些使用减号而不是 except,有些则根本不支持这种语法。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-08
    相关资源
    最近更新 更多