将新记录传输到链接服务器的存储过程失去连接

Stored procedure transferring new records to linked server losing connection

首先声明我不是 sql 专家。预先感谢您审阅我的问题。

我在使用存储过程时遇到了一些问题,该存储过程在将新记录传输到 table 的过程中定期失去与链接服务器的连接(很多记录)。我想知道一些事情。

首先,有没有更好的方法可以更快更高效的完成任务?

其次,是否有一种方法可以更好地处理连接丢失问题,尝试重试上一步以从中断处继续,可能在等待 15 分钟左右之后如果与链接服务器有一些临时断开连接(可能持续时间超过终止前允许的时间)?

另外我很好奇,当发生类似突出显示的步骤时,如果正在对链接服务器执行 sql,并且连接丢失,sql 尝试重新连接并在超时期间继续,或者因为这是一个比较语句,它会中断吗? 我真的不明白它是如何工作的。

这是连接丢失最常见的部分,通常发生在第一个插入语句中(begin catch 块中的第一步):

UPDATE [LINKEDSERVER.XYZ.COM].dest_database1.dbo.run
  SET last_result = 32
  WHERE type = 158;

BEGIN TRY
    INSERT INTO [LINKEDSERVER.XYZ.COM].[dest_database2].dbo.table1 ( CID , BID , Question1 , Question2 , Question3 , Question4 , Question5 , Question6 , Question7 , Question8 , Question9 , Question10 , Comments , EmailAddress , Name , Address , Address2 , City , State , Zip ) 
    SELECT src.CID , src.BID , src.Question1 , src.Question2 , src.Question3 , src.Question4 , src.Question5 , src.Question6 , src.Question7 , src.Question8 , src.Question9 , src.Question10 , src.Comments , src.EmailAddress , src.Name , src.Address , src.Address2 , src.City , src.State , src.Zip 
      FROM table1 AS src LEFT OUTER JOIN [LINKEDSERVER.XYZ.COM].[dest_database2].dbo.table1 AS dst ON src.CID = dst.CID AND src.BID = dst.BID
      WHERE dst.CID IS NULL;

    INSERT INTO [LINKEDSERVER.XYZ.COM].[dest_database2].dbo.table2 ( CID , AccountNumber , Name , Address , Address2 , City , State , Zip , BShort, EmailAddress ) 
    SELECT src.CID , src.AccountNumber , src.Name , src.Address , src.Address2 , src.City , src.State , src.Zip , src.BShort, src.EmailAddress 
      FROM table2 AS src LEFT OUTER JOIN [LINKEDSERVER.XYZ.COM].[dest_database2].dbo.table2 AS dst ON src.BShort = dst.BShort
      WHERE dst.BShort IS NULL;
END TRY
BEGIN CATCH
    SELECT @ErrorCode = @@Error;
    SELECT @ErrorResult = 109;
    SELECT @ErrorMessage = 'Failed Copy ' + CAST ( @ErrorCode AS varchar ) ;
    GOTO ExitWithError;
END CATCH;

INSERT INTO [LINKEDSERVER.XYZ.COM].dest_database1.dbo.system_log ( notes , log_type , source_type , parent_id ) 
VALUES ( 'Copied tables xyz ' , 45 , 58 , 0 ) ;

UPDATE [LINKEDSERVER.XYZ.COM].dest_database1.dbo.run
  SET last_result = 31
  WHERE type = 158;

我知道如果连接丢失,我的 catch 块不会执行,所以不会使用 ExitWithError。而且我想我明白当连接丢失时会发生回滚(不确定 how/if 这是否适用于链接服务器,因为发生这种情况时会传输一些记录),并且它只是退出执行所有操作 - 因为 catch 和被执行或整个 begin catch 块之后的语句。我希望,如果发生这种情况,记录一些东西,以便存储过程在再次 运行s 时(每 30 分钟设置为 运行 直到成功),它可以从它离开的地方开始关闭,因为我在开始时有代码查找最后的 status/log 条目并确定要做什么。 有没有更好的方法来处理这个问题?

所以首先提示,如果可以的话,从其他服务器(目标)执行存储过程。换句话说,切换本地和链接服务器。原因是我已经显着提高了从链接服务器到本地 table 的 DML (insert/update/delete) 命令的性能。将 DML 做成链接 table 时,性能很糟糕!

接下来有效地使用 id,它们是连续的吗?你能不能只取目标服务器上的最大值,而不必在服务器之间加入大 tables?

如果您不能指望顺序,那么您可以在源服务器上构建临时 table 并在那里进行过滤,而不是尝试跨 table 进行过滤。如果只是 id,您还可以尝试以 nvarchar 格式来回传递 XML。或者您可以在源上维护跟踪 table,这样您就可以使用 OUTPUT inserted.id INTO .... 从您的插入语句中知道已经处理了哪些 ID。

最后将您的程序设置为 batch/cut 并以较小的块进行交易,例如一次 SELECT TOP x# 条记录。您仍然可以将整个事情放在一个 while 循环中,以便它在 proc 的一次执行中完成所有事情,但是您可以将您的事务分成更小、更易于管理的部分。