【问题标题】:Ideas on incorrect ORDER BY results关于错误 ORDER BY 结果的想法
【发布时间】:2021-02-02 02:38:50
【问题描述】:

我想强调的是,我正在寻找想法,不一定是具体的答案,因为很难显示我的查询是什么样的,但我认为没有必要。

流程如下:

  1. 表 A 不断填满,就像一个桶一样 - SQL 作业每分钟或更短时间都会调用 SP_Proc1,并将多条记录插入表 A。

  2. 同时,C# 进程每分钟或更短时间不断调用另一个过程 SP_Proc2,从表 A 中进行有序的 TOP 5 选择并将结果返回给 C# 方法。在 C# 代码完成处理结果后,它会从表 A 中删除选定的 5 条记录。

我将上面有问题的部分加粗。有必要按指定的顺序一次处理 5 个表 A 中的记录,但每月几次 SP_Proc2 以错误的顺序选择排序的 TOP 5 记录,即使所有记录都存在于表 A 中并且具有正确的用于排序的列值。

注意事项:

  • 我按整数排序,而不是 varchar。
  • C# 部分使用 1 个线程。
  • SP_Proc1 和 SP_Proc2 都使用事务并使用 READ COMMITTED 或 READ COMMITTED SNAPSHOT 事务隔离级别。
  • 用于排序的一列是计算值,但非常简单。它只是检查表 A 中的另一列是否不为空,并将计算列设置为 1 或 0。
  • 在主键 Id 上有一个唯一的非聚集索引和一个由用于 SP_Proc2 中排序的相同列组成的聚集索引。
  • 我使用的是 SQL Server 2012 (v11.0.3000)

我开始认为这可能是一个 SQL 错误,或者可能是表 A 中的记录或索引被损坏,然后被 C# 进程删除,这就是我无法捕捉到它的原因。

编辑:

为了澄清,SP_Proc1 一次将一大批 N 记录提交到表 A,SP_Proc2 以 5 个批次从表 A 中提取记录,它对表中的记录进行排序并选择 TOP 5,有时选择了错误的批次,批次本身是正确订购的,但应该根据 ORDER BY 选择不同的批次。我相信Rob Farley 可能有正确的想法。

【问题讨论】:

  • ORDER BY 不会被忽略;这意味着可能的原因是您误解了某些东西,或者该过程存在缺陷。老实说,没有任何代码,我猜是后者。
  • 换一种说法,您为什么要运行 SQL Server 2012 SP1?为什么8年没有更新(SP1在212年11月出来)?
  • SQL Server 是多线程的,不按顺序存储数据。因此,当您进行查询时,您总是需要 top 执行 orderby 才能以正确的顺序获取数据。现在,当您使用 top 时,您将在查询运行时获得顶部,并且可能会在查询运行后立即更改。因此,如果您想删除相同的前五个项目,则必须使用 WHERE 来删除,该 WHERE 唯一标识您要删除的五个 tiems。
  • 认为这可能是一个 SQL 错误 不——作为程序员,您应该始终怀疑自己的代码是问题的根源。并且有很多关于使用表作为队列的讨论 - 这可能是一个很好的起点。
  • "认为这可能是一个 SQL 错误" 即使它您使用的是 8 年前的版本;因此,第一步是安装最近 8 年的更新。

标签: c# sql-server tsql sql-order-by


【解决方案1】:

我的猜测是您的“乱序 TOP 5”是有序的,但后面的五个重叠。比如,一次你得到 1231、1232、1233、1234 和 1236,下一批是 1235、1237,依此类推。

这可能是锁定和阻塞的问题。您已经表明您的进程使用事务,所以如果您的 1235 尚未提交,我不会感到惊讶,但可以通过您的快照隔离忽略,并且您的 1236 可以被拾取。

听起来这里没有错误。我上面描述的是快照隔离的一个明确特征。如果您必须在比 1236 更早的批次中提取 1235,则不要使用快照隔离,并强制锁定您的表,直到每个插入块完成。

【讨论】:

  • 我认为您正在做某事。澄清一下,SP_Proc1 一次向表 A 提交大量 N 条记录(最多 5000 条),SP_Proc2 以 5 条为一组从表 A 中提取记录,它首先对记录进行排序,然后选择 TOP 5,有时会出现错误的批次选择。我仍然不确定 SNAPSHOT 如何在这里发挥作用,但我会调查一下。谢谢!
【解决方案2】:

另一种建议是在读写过程中使用表锁(tablock)。

虽然这很昂贵,但如果你想要绝对的一致性,那么这可能是要走的路。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-04-27
    • 2013-11-19
    • 1970-01-01
    • 2021-03-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多