存储过程在 7 年后随机停止工作

Posted

技术标签:

【中文标题】存储过程在 7 年后随机停止工作【英文标题】:Stored Procedure randomly stopped working after 7 years 【发布时间】:2013-10-28 17:31:40 【问题描述】:

我在一家对冲基金工作,我们的数据库系统最近开始出现问题。我做了一些调查,实现了错误代码以及每个进程之间的消息框。我终于找到了问题所在:它似乎在 SQL 的存储过程中。

我们在 Windows XP SP3 上使用 VB 2005、Access for SQL 表视图和 Microsoft Server Management Studio Express。

所有其他进程都在工作。以下是它的工作原理:

我们填写来自bloomberg 的交易,该交易创建一个.csv 文件。这个 .csv 文件被放入一个名为 BBGT_Transactions 的 SQL 表中。是直接复制。这个过程完美无缺。每次流程运行时(每 30 分钟),事务都在那里。接下来,相同的流程将事务处理在 BBGT_Transactions 中并将其复制到 Transactions。来自 VB 的调用如下所示:

 Public Sub CopyNewEMSTransactions()

        Log.Info("Copying new transactions from BBGTransactions to Transactions")
        DAL.sqlcmd("CopyNewEMSTransactions")

End Sub

CopyNewEMSTransactions 是一个存储过程,如下所示:

USE [IPAS]
GO
/****** Object:  StoredProcedure [dbo].[CopyNewEMSTransactions]    Script Date: 10/28/2013 13:34:15 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author:      Name
-- Create date: 
-- Description: 
-- =============================================
ALTER PROCEDURE [dbo].[CopyNewEMSTransactions] 
    -- Add the parameters for the stored procedure here
AS
BEGIN
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for procedure here

--New Code: Accounts for option trades through bloomberg terminal
INSERT INTO Transactions (Account, TDate, [Time], SDate, Class,
                              [Type], Ticker, Quantity, Price, SEDOL,
                              CUSIP, Comments, OrderNumber, ISIN)
    SELECT TranAccount AS Account,
           (SELECT CAST(FLOOR(CAST(ExecDate AS float)) AS datetime)) AS TDate,
           ExecDate + ExecTime - '1899-12-30' AS [Time],
           ExecDate + 3 AS SDate, CASE EMS.Broker
                                    WHEN 'CIBC' THEN 'Equity'
                                    WHEN 'CIBO' THEN 'Option' END AS Class,
          CASE Side
            WHEN 'SS' THEN 'SHORT'
            WHEN 'B' THEN 'BUY'
            WHEN 'S' THEN 'SELL'
            WHEN 'BS' THEN 'BUY'
            ELSE 'UNKNOWN' 
          END AS Type, EMS.Ticker,
          CASE Side
            WHEN 'SS' THEN -1
            WHEN 'S' THEN -1
            WHEN 'B' THEN 1
            WHEN 'BS' THEN 1
          END * FillAmount AS Quantity, 
          AveragePrice AS Price,
          SEDOL, CUSIP,
          Comments = 'Bloomberg data',
          LatestRows.OrderNumber, ISIN
    FROM    
        (SELECT Ticker, OrderNumber, MAX(ExecSeqNumber) AS LastExecSeqNumber
        FROM BBGTransactions
        WHERE OrderNumber NOT IN (SELECT OrderNumber FROM Transactions 
                                  WHERE Comments = 'Bloomberg data')

        GROUP BY OrderNumber, Ticker) LatestRows
    LEFT JOIN
        --Changed from "SELECT * From BBGTransactions" to add the ' Equity'
        (SELECT BBG_ID, ExecDate, ExecTime, TranAccount, 
            CASE Broker
                WHEN 'CIBC' THEN Ticker
                WHEN 'CIBO' THEN Ticker + ' Equity' END AS Ticker,
        --With option trades, SEDOL is not used anywhere. It used to be used for the Reconciliation report
        --but that report has been changed to look at option ticker instead.
        CASE Broker
            WHEN 'CIBC' THEN SEDOL
            WHEN 'CIBO' THEN NULL END AS SEDOL, 
        CUSIP, OrderNumber, Side, FillAmount, AveragePrice, ExecLastFillPX, Broker, Currency, OrderType, 
        LimitPrice, DayFillAmount, DayAvgPrice, ISIN, Amount, ExecType, ExecSeqNumber, ExecPrevSeqNumber FROM BBGTransactions) EMS
    ON LatestRows.LastExecSeqNUmber = EMS.ExecSeqNumber
       AND LatestRows.OrderNumber = EMS.OrderNumber
    WHERE LatestRows.OrderNumber NOT IN (SELECT OrderNumber FROM Transactions 
                              WHERE Comments = 'Bloomberg data')

END

它没有返回错误并显示“正在将 BBGT 复制到事务表”,然后显示“完成”但不复制!!它工作了 7 年,大约 3 周前停止工作。

注意事项:

上个月我们的网络断断续续 我怀疑 Windows 更新已运行,并且在此之前大约 3 年以上没有更新 Windows。我上次检查时有 70 个更新,现在没有了。 回到幽灵是我最后的选择,因为这需要我做很多工作才能实现 代码从未更改过! 我曾尝试只运行存储过程,但它什么也不做,正如怀疑的那样。

编辑 有一个跟踪日志,只运行程序。但它没有返回错误?

SELECT SYSTEM_USER
go
SET ROWCOUNT 0 SET TEXTSIZE 2147483647 SET NOCOUNT OFF SET CONCAT_NULL_YIELDS_NULL ON SET ARITHABORT ON SET LOCK_TIMEOUT -1 SET QUERY_GOVERNOR_COST_LIMIT 0 SET DEADLOCK_PRIORITY NORMAL SET TRANSACTION ISOLATION LEVEL READ COMMITTED SET ANSI_NULLS ON SET ANSI_NULL_DFLT_ON ON SET ANSI_PADDING ON SET ANSI_WARNINGS ON SET CURSOR_CLOSE_ON_COMMIT OFF SET IMPLICIT_TRANSACTIONS OFF SET QUOTED_IDENTIFIER ON
go
select @@spid select SERVERPROPERTY('ProductLevel')
go
USE [IPAS]

go

DECLARE @return_value int

EXEC    @return_value = [dbo].[CopyNewEMSTransactions]

SELECT  'Return Value' = @return_value


go
exec sp_execute 18,5930,5924,5925,5926,5927,5928,5929,5923,5921,5922
go
exec sp_execute 16,59826,59827,59756,59757,59758,59716,59715,59700,59701,59702
go

还有对应的excel表格:

链接,如果很难看到:

http://i.stack.imgur.com/iJFRo.png


选择语句#1(似乎正在工作):

SELECT Ticker, OrderNumber, MAX(ExecSeqNumber) AS LastExecSeqNumber
FROM BBGTransactions
WHERE OrderNumber NOT IN (SELECT OrderNumber FROM Transactions
                          WHERE Comments = 'Bloomberg data')
GROUP BY OrderNumber, Ticker

返回:

链接:http://imgur.com/3A8E1JR

选择 2:

代码:

SELECT BBG_ID, ExecDate, ExecTime, TranAccount,
    CASE Broker
        WHEN 'CIBC' THEN Ticker
        WHEN 'CIBO' THEN Ticker + ' Equity' END AS Ticker,
    --With option trades, SEDOL is not used anywhere. It used to be used for the Reconciliation report
    --but that report has been changed to look at option ticker instead.
    CASE Broker
        WHEN 'CIBC' THEN SEDOL
        WHEN 'CIBO' THEN NULL END AS SEDOL,
    CUSIP, OrderNumber, Side, FillAmount, AveragePrice, ExecLastFillPX, Broker, Currency, OrderType,
    LimitPrice, DayFillAmount, DayAvgPrice, ISIN, Amount, ExecType, ExecSeqNumber, ExecPrevSeqNumber 
    FROM BBGTransactions
    WHERE LatestRows.OrderNumber NOT IN (SELECT OrderNumber FROM Transactions
                                         WHERE Comments = 'Bloomberg data')

错误 服务器:消息 4104,级别 16,状态 1,行 1 无法绑定多部分标识符“LatestRows.OrderNumber”。

【问题讨论】:

在启用“实际执行计划”选项的情况下运行存储过程,看看哪些步骤会意外影响零行。 七年后,数据库 .mdb 文件的大小是否达到了 2GB? 从 proc 中取出 SELECT 语句并将其放入查询分析器窗口中,查看它是否运行,以及出现什么结果。当我遇到这些问题时,我开始注释部分 where 子句,然后加入以找出我的记录在哪里过滤。 Transactions.OrderNumber 是不可为空的列吗?如果它可以为空,是否有任何记录具有空值?如果里面有一个空值,NOT IN 子句就会中断,因此如果该表中潜入了一条坏记录,您的整个查询将是空的。 @Phils - 不,通常日志不会像解构查询那样快速。开始取出部分查询,直到找到问题所在。每个人都在暗示它的数据现在与查询的预期不匹配。 【参考方案1】:

您为对冲基金工作,获得标准许可证并且不使用免费赠品。

看起来您发布的不是实际的存储过程,而是一个“清理过的”版本来展示它是如何工作的。这实际上是一种阻碍,而不是一种帮助。

在这个删除时很难说,但我会说你有数据问题(查询完全按照它的方式运行,但你拥有的数据没有返回任何结果),或者你最终超过Express 版本中内置的限制。

忘记运行 SP,提取查询并直接运行它们,感受一下数据的实际样子。如果选择有效但插入无效,您可能已经超出了快速版本的限制。如果选择没有返回预期的行,那么您有数据问题。

【讨论】:

【参考方案2】:
-I have tried running ONLY the stored procedure and it does nothing.

您希望它返回什么?它是否显示任何受影响的行?

NO CODE WAS CHANGED EVER

您确定架构没有改变吗?您是否尝试运行查询并亲自查看它是否有效? (在没有来自 SP 的插入命令的情况下运行 select)

您确定您使用的是正确的数据库吗?这也可能会改变..

您确定您的 VB 代码确实完成了吗?我会尝试在 SP 执行后打印日志,这里可能存在我们看不到的异常。

【讨论】:

代码中绝对没有任何变化。我 100% 肯定这一点,因为我是唯一可以访问实际代码的人。数据库是正确的,我们没有很多,代码没有改变,数据库名称也没有改变(否则其他代码都不会运行,它会运行) VB 代码确实完成了。我创建了一个消息框以在完成时显示“DONE”,并且在运行时我们有控制台日志。我可以看到它运行存储过程以及何时完成。另外,我尝试只运行存储过程,它说它运行但没有任何变化。 @Phils - 我相信你 :) 环境也会发生变化。这是我将从检查开始的基本内容,添加日志将使您接近找到解决方案。 谢谢约西。抱歉,如果我遇到粗鲁,这不是我的意图,您的回答绝对有帮助。关于打印实际日志的事情......我试图实现一个真正的日志文件,但它不会打印到日志中,所以我放弃并继续使用控制台和消息框。它创建了日志文件但将其留空? @Phils - 没问题,如果您想确保它完成,您必须在 SP 完成后立即打印日志(可能有代码捕获此异常)。你 100% 确定吗? 我正在创建一个跟踪,但我遇到了问题。我们使用的是 2005 SQL server management studio express【参考方案3】:

计算机不会“随机”.. 发生了一些变化,导致了意想不到的结果。单步执行代码是确定的唯一方法..

【讨论】:

以上是关于存储过程在 7 年后随机停止工作的主要内容,如果未能解决你的问题,请参考以下文章

存储过程停止工作

长存储过程在某些 exec 之后停止返回结果,为啥?

一旦违反条件,停止存储过程的进一步执行?

Dapper 在使用存储过程更新表后停止拉连接表

如何停止在 MySQL 中执行完整的存储过程?

存储过程生成复杂的随机编号