【问题标题】:T-SQL stored procedure with dateadd fails带有 dateadd 的 T-SQL 存储过程失败
【发布时间】:2018-08-21 16:38:52
【问题描述】:

我的存储过程中看似简单的部分似乎失败了,日期比较。我正在寻找超过 5 分钟的最早订单以开始处理。

python 程序调用存储过程来获取订单号并开始处理它。每次触摸订单都会修改o.chg_date,可能会延长 5 分钟的延迟。在订单创建过程中,有时销售人员会合并两个订单。他们需要这个 5 分钟的窗口来这样做。

这是存储过程的简化版本,但在其他 where 子句中是典型的。

CREATE PROCEDURE [dbo].[Get_Next_Order] 
AS
    SELECT TOP 1 o.order_id
    FROM orders o (NOLOCK)
    WHERE
        o.order_state = 4               -- ready to be processed
        AND o.order_status <> 3         -- not a deleted order
        AND o.items > 0                 -- not an empty order
        AND o.chg_date < DATEADD(mi, -5, GETDATE())     -- 5 minute delay after ready
    ORDER BY
        o.chg_date

问题:在十几个订单中,两个将在 5 - 10 秒内得到处理。

我是否错误地使用了DATEADD 函数?它确实有 80% 的时间有效。而且我不能通过简单地在 SSMS 中运行代码来让它失败。

我能想到的唯一另一件事是,order_state = 4chg_date 还没有更新。关于比赛条件解决的任何建议?

order_state 由代码更新。 chg_date 由触发器更新。

【问题讨论】:

  • 正确。在 12:36 准备好的订单将需要再等一分钟才能处理。一旦处理完毕,order_state 将增加到 5。
  • 我不确定你所说的“失败”是什么意思,当它“失败”时会发生什么?
  • 历史文件显示,在 order_state 变为 = 4 后的 10 秒内,部分订单正在处理中,已被跟踪。这意味着 o.chg_date 比较失败,没有感觉到延迟。该订单不应该被处理。当我从 SP 中取出查询并在 SSMS 中运行时,它从来没有提出过没有完整 5 分钟延迟的订单。
  • 我认为您有竞争条件,可能需要调查排他锁或其他方法。

标签: sql sql-server race-condition dateadd


【解决方案1】:
if object_id(N'TempDB.dbo.#orders') is not null
    drop table #orders;

--this time is too new (papa bear)
Select
    1 As Order_id
    ,4 As Order_state
    ,1 As Order_status
    ,11 As Items
    ,sysdatetime() As Chg_date
into #orders
union All
--this time is too old (momma bear)
Select
    2 As Order_id
    ,4 As Order_state
    ,1 As Order_status
    ,11 As Items
    ,dateadd(hour,-1,sysdatetime()) As Chg_date
union all
--this time is just right (baby bear)
Select
    3 As Order_id
    ,4 As Order_state
    ,1 As Order_status
    ,11 As Items
    ,dateadd(minute,-6,sysdatetime()) As Chg_date;

-----------------------only copy bottom section into your stored proc-----------------------------
with top_order as
(
    Select
        order_id
        ,Chg_date
        ,row_number() over (order by chg_date desc) as Row_num
    From
        #orders O (Nolock)
    Where
        O.Order_state = 4                   -- ready to be processed
        And O.Order_status <> 3             -- not a deleted order
        And O.Items > 0                     -- not an empty order
        and O.Chg_date <= dateadd(minute,-5,sysdatetime())
)

select order_id
from Top_order
where row_num = 1;

【讨论】:

  • 对不起,这些熊是什么意思?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-10-03
  • 2013-05-28
  • 2011-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多