Sql-Server

如何防止 ssis 包中的並發問題?

  • June 19, 2019

擁有 SQL Server 2017 伺服器。

有多個使用 SYNCHRONIZED 標誌呼叫單個 SSIS 包的 SQL Server 作業。

在包中有一個執行儲存過程(請參見下文)的數據流,該過程返回一個數據源,該數據源檢查是否有要列印的標籤。如果有任何標籤要列印,那麼它將這些標籤選擇到表變數中,選擇標籤,並更新標籤 IsProcessed 標誌以表明它們已被處理。問題是,如果有多個作業呼叫包裹,那麼即使只有一個標籤需要處理,它也會列印出多個標籤。這種情況不會一直發生。所以,我的問題是:如何防止這種情況發生?

CREATE PROC [dbo].[spCreateOutput_LabelDataSet]

AS

BEGIN
   BEGIN TRY
       BEGIN TRAN

       DECLARE @Intermediate TABLE(
           PrintLabelsID INT NULL,
           Labels XML NULL
       )

       INSERT INTO @Intermediate(PrintLabelsID, Labels)
       SELECT
           pl.PrintLabelsID,
           pl.Label
       FROM
           Staging.dbo.PrintLabels pl
       WHERE
           pl.IsProcessed = 0

       SELECT
           CAST(Labels AS VARCHAR(MAX)) 'Labels'
       FROM
           @Intermediate i

       UPDATE pl
       SET IsProcessed = 1,
           ProcessedDate = GETDATE()
       FROM
           Staging.dbo.PrintLabels pl
           INNER JOIN @Intermediate i
               ON i.PrintLabelsID = pl.PrintLabelsID

       COMMIT TRAN
   END TRY
   -- Error Logging
   BEGIN CATCH
       IF @@TRANCOUNT > 0
           BEGIN 
               ROLLBACK TRANSACTION;
               DECLARE @ErrorNumber INT = ERROR_NUMBER();
               DECLARE @ErrorLine INT = ERROR_LINE();
               DECLARE @ErrorMessage NVARCHAR(4000) = LEFT(ERROR_MESSAGE(), 4000);
               DECLARE @ErrorSeverity INT = ERROR_SEVERITY();
               DECLARE @ErrorState INT = ERROR_STATE();
               DECLARE @Error_Procedure VARCHAR(200) = LEFT(ERROR_PROCEDURE(), 200);

               EXEC Logs.dbo.spTrackErrors @ErrorNumber, @ErrorSeverity, @ErrorState, @Error_Procedure, @ErrorLine, @ErrorMessage;
               THROW;
           END;
   END CATCH

END

由於似乎這個包的任何並發執行都會給您帶來這個問題,我建議將控制項放入包中,以防止在另一個作業正在執行時執行它。

據我所知,SSIS 中沒有將包設置為“一次只執行一次”的機制,因此您需要在 SQL 數據庫中實現此解決方案。創建一個記錄正在執行的包的每個實例的表(無論如何,這對於審計/調試目的很有用)並記錄包執行的開始/結束時間,可能還有一個狀態列。如果有作業仍在執行,則結束時間將為空,因此您的包應檢查這一點,如果存在則退出。

這種方法的風險是致命錯誤可能會導致未完成的行保留在表中,從而阻止任何進一步的執行。您應該在包中放入一些東西以在所有錯誤情況下對其進行更新,如果工作持續時間過長,可能還有一些邏輯來完成一項工作(弄清楚這個持續時間是一個業務問題)

引用自:https://dba.stackexchange.com/questions/240826