SQL Server 2016 可以在一个事务中重新排列多个查询的顺序吗?

Posted

技术标签:

【中文标题】SQL Server 2016 可以在一个事务中重新排列多个查询的顺序吗?【英文标题】:Can SQL Server 2016 Rearrange Order of Multiple Queries in One Transaction? 【发布时间】:2021-11-27 22:14:04 【问题描述】:

我遇到了与多查询事务有关的非常奇怪的事件。在 SQL Server 从 2008 年更新到 2016 年之后(我们的主机没有发出警告),我们在数据发布到 API 后开始删除数据。奇怪的是,有些数据到了,有些没有。

为了保护完整性,所有查询都连接在一个事务中。可以创建记录,然后在以后更新。它们的格式类似于:

DELETE FROM table_1 WHERE parentID = 123 AND col2 = 321;
DELETE FROM table_2 WHERE parentID = 123 AND col2 = 321;
-- etc
INSERT INTO table_1 (parentID, col2, etc) VALUES (123, 321, 123456);
INSERT INTO table_2 (parentID, col2, etc) VALUES (123, 321, 654321);
-- etc

可能有数百行正在执行。由于设计原因,相关记录没有唯一 ID,因此执行查询的最高效方式是首先删除匹配的记录,然后重新插入它们。循环遍历记录并检查是否存在是唯一的其他选择(据我所知),而且有这么多的记录会很昂贵。

无论如何,我一直在努力寻找这种数据丢失的原因,这似乎是随机的。我有 sql 查询的日志,所以我知道它们的格式正确并且所有数据都完好无损。最后,我唯一能想到的就是将 DELETE 查询分离到一个单独的事务中并首先执行*。这似乎解决了问题。

问。有谁知道这些查询是否可以按照它们出现的顺序执行?你有没有更好的方法来编写这些交易?

* 我不一定喜欢这个解决方案,因为删除查询是我想要交易的主要原因。如果在第二个事务期间发生错误,则所有较旧的匹配记录都已删除,但永远不会保存较新的版本。生活在边缘......

附:我遇到的另一个问题,这可能是由于我对平台的无知,当我试图用BEGIN TRAN;COMMIT TRAN; 将这些查询括起来时,在此脚本完成后立即,同一线程中的任何后续查询都挂了大约20-30秒左右。我究竟做错了什么?如果一次执行所有查询,我真的需要这些动词吗?

【问题讨论】:

您可能希望在(parentID, col2) 上建立一个聚集索引,此外,您应该考虑将所有更改转储到一个临时表或表值参数中,并执行单个连接delete 和连接update。是的,如果您没有事务,那么每个批次都可能相互干扰,事务会创建锁以防止这种情况发生,从而导致阻塞 谢谢,聚集索引是个好主意(该应用程序是旧的,用 ASP Classic 编写,在生产大约 7 年后即将停产)。就 TSQL 而言,TVP 可能高于我的薪酬等级,但我一定会调查一下。 TVP 非常简单且非常有用,但您无法强迫经典 ASP 了解它们是什么。 再次考虑使用聚集索引时,拥有它们会很棒,但在 MSN 文档中,有几个非常严重的警告要在已经包含大量数据的表上创建它们。他们文档中的这一行总结了这一点:在大型表上构建索引的首选方法是从聚集索引开始,然后构建任何非聚集索引。 那是因为聚集键是每个非聚集索引的一部分,所以非聚集索引也必须重建;这是一次性操作,因此请计划在非工作时间或低使用时间进行,如果您使用的是企业版,则可以在线重建(尽管名称有点误导)。这也是一种快速(相对)整理索引和更新统计信息的方法。 【参考方案1】:

我们可以使用更多信息,例如您的表是否存在唯一约束并忽略重复插入。 如果数据丢失,可能是由于插入失败,这将在“错误和警告”事件类下的 Profiler 事件“用户错误消息”中注册一个条目。创建跟踪以仅过滤此登录并检查每个语句以及跟踪中是否出现任何用户错误。 如果您有其他进程正在运行(其他应用程序或线程),则可能在您插入记录后,其他人在您不知情的情况下删除了该行。在这种情况下,您可能希望设置一个删除触发器来记录表上的所有更新和删除操作,并查看执行这些操作的用户是什么。简而言之,如果你认为你丢失了数据,要么是命令未执行,要么执行错误,要么执行后删除购买其他进程。

【讨论】:

这个数据库没有限制。该数据库托管在共享服务器上,我无权访问 Enterprise Manager。我已经彻底错误地捕获了执行的查询,并且没有抛出任何错误。我保留了查询日志并自己手动运行它们 - 我立即检查数据并发现一些丢失(没有其他帐户或进程可能删除它们)。我剩下的最后一个选择是相信 SS2016 以某种方式解析了查询的原始顺序,并且修复工作证实了这一理论。

以上是关于SQL Server 2016 可以在一个事务中重新排列多个查询的顺序吗?的主要内容,如果未能解决你的问题,请参考以下文章

在 SQL Server 2008 R2 中重命名数据库时出错

MSSQL sql server 2005/2008 row_number()函数应用之–删除表中重

SQL Server 触发器插入导致锁定直到提交

SQL Server 抛出和事务

SQL Server 数据库事务日志文件大小急剧增加

如何在 MySQL 的一个原子操作中重命名两个表