【问题标题】:SQL Server seems to behave in an async mannerSQL Server 似乎以异步方式运行
【发布时间】:2014-10-02 09:20:03
【问题描述】:

我知道默认情况下 SQL 语句不会异步执行,但我遇到的情况似乎是这样的。

表格

  • [#data]
  • [tbl_Bucket]
  • [tbl_IDPool]

程序

  • [sp_InsertIntoBucket]
  • [sp_GenerateID]
  • [sp_UpdateIDPool]

流程

  • 一个应用程序调用[sp_InsertIntoBucket]
  • [sp_InsertIntoBucket] 致电[sp_GenerateID]
  • [sp_GenerateID] 查询[tbl_IDPool] 并生成一个值
  • [sp_GenerateID] 致电[sp_UpdateIDPool]
  • [sp_UpdateIDPool] 写信给[tbl_IDPool]
  • [sp_GenerateID] 将其生成的值返回给 [sp_InsertIntoBucket]
  • [sp_InsertIntoBucket] 使用该值作为 [tbl_Bucket] 中新记录的主键
  • [sp_InsertIntoBucket] 将生成的值返回给调用者

场景

[#data] 具有发往[tbl_Bucket] 的信息(1500 - 12000 条记录)。由于 [sp_InsertIntoBucket] 一次只能处理一条记录,因此该过程是 RBAR 的 - 对于 [#data] 中的每条记录,都会调用 [sp_InsertIntoBucket]

问题

[sp_GenerateID] 生成重复值。在[sp_InsertIntoBucket] 中的实际INSERT 发生并引发错误之前,我已经有13 到130 个重复的生成值。

生成的值取决于[tbl_IDPool] 中的数据,因此对于每个[sp_GenerateID] 调用调用[sp_UpdateIDPool] 以确保下一个 [sp_GenerateID] 调用生成一个独特的价值。

我怀疑这与[sp_GenerateID][sp_UpdateIDPool] 完成对[tbl_IDPool] 的写入之前被第二次调用有关。但这没有任何意义,因为 RBAR 应该等待 [sp_InsertIntoBucket],后者应该等待 [sp_GenerateID],后者应该等待 [sp_UpdateIDPool],然后再移动到下一个 [#data] 条目,对吧?

我的尝试

  • WAITFOR DELAY "00:00:00.003" - 这行得通,但我正在寻找更好、更高效、更优雅的解决方案。
  • WHILECURSOR - 唯一的区别是 CURSOR 稍慢。
  • [tbl_IDPool][sp_GenerateID] 查询中使用和不使用 WITH (NOLOCK) 希望写入(第一次调用)会锁定读取(第二次调用)。

【问题讨论】:

  • 您应该避免在存储过程名称的开头使用sp_。文档中有警告说这是为 Microsoft 的 system 程序保留的,如果存在名称冲突(现在,或者可能以后系统更新),Microsoft 将“获胜”。
  • @Damien_The_Unbeliever 这很有趣。感谢您的提醒。我没有意识到这一点,并且将来会这样做 - 或者我应该说这样做。然而,在这种情况下,它只是为了区分实体类型。您的警告已被记录。
  • 不同事务之间有并发,对吧?为什么您认为存在事务内异步?竞争条件似乎很好地解释了这种行为。
  • 感谢您抽出宝贵时间;感谢您的意见。我没想到 SQL Server 会以这种方式运行,因为 RBAR 循环正在向所有其他过程启动“调用堆栈”。它 [顶级的外部会话] 不能与自身并发,可以吗?也许我没有正确理解你。
  • 对 SQL Server 的单个查询永远不会创建并发(如果您确实想要并行性,这会很烦人)。当您调用 proc 时,该调用是同步和阻塞的。我很确定你是否说过,但很可能有多个事务(在不同的会话中)在这里对相同的数据进行操作。尝试答案中的 SERIALIZABLE 建议来测试该理论。 SERIALIZABLE 提供了单线程执行的假象。

标签: sql-server tsql stored-procedures rbar


【解决方案1】:

[sp_GenerateID]开头尝试指定

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE

然后将剩余的内容包含在事务块中。

BEGIN TRANSACTION
...
COMMIT TRANSACTION

【讨论】:

  • 感谢您抽出宝贵时间回复。我在几个不同的地方尝试了你建议的声明,但一直得到Incorrect syntax near 'SERIALIZABLE'.,所以我用谷歌搜索得到了这个:stackoverflow.com/questions/6342732/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多