我经历了一个与多查询事务相关的非常奇怪的事件。在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秒左右。我做错了什么?如果所有查询都在一次执行,我真的需要这些动词吗?
我们可以使用更多的信息,例如,如果您的表上有唯一约束,则忽略重复插入。如果数据丢失,则可能是由于插入失败,这将在分析器事件中注册一个条目"用户错误消息"。在"错误与警告"下;事件类。创建跟踪以仅过滤此登录,并检查每个语句以及在跟踪中是否引发了任何用户错误。如果您有其他进程正在运行(其他应用程序或线程),则有可能在您插入记录之后,在您不知情的情况下删除了该行。在这种情况下,您可能希望设置一个删除触发器来记录表上的所有更新和删除操作,并查看执行这些操作的用户是谁。简而言之,如果您认为丢失了数据,要么是命令没有执行,要么是执行错误,要么是执行后删除了其他进程。