Kontrollera stora SQL-resultatuppsättningar och tidsgränser under lagrade procedurer i arbetsflöden för Azure Logic Apps

Gäller för: Azure Logic Apps (Förbrukning + Standard)

För att enklare automatisera affärsuppgifter som fungerar med SQL-databaser kan arbetsflödet använda SQL Server-anslutningsåtgärder, som innehåller många serverdelsfunktioner som arbetsflöden kan använda i Azure Logic Apps.

I vissa situationer kan arbetsflödet behöva hantera stora resultatuppsättningar. Dessa resultatuppsättningar kan vara så stora att SQL Server-anslutningsåtgärder inte returnerar alla resultat samtidigt. I andra situationer kanske du bara vill ha mer kontroll över storlek och struktur för dina resultatuppsättningar. Om du vill ordna resultaten på det sätt du vill kan du skapa en lagrad procedur.

När en SQL Server-anslutningsåtgärd till exempel hämtar eller infogar flera rader kan arbetsflödet iterera genom dessa rader med hjälp av en Until-loop som fungerar inom dessa gränser. Om arbetsflödet måste hantera tusentals eller miljontals rader vill du minimera kostnaderna som uppstår vid anrop till SQL Server-anslutningsappen till SQL-databasen. Mer information finns i Hantera massdata med hjälp av SQL-anslutningsappen.

Den här guiden visar hur du styr storlek, struktur och tidsgränser när du bearbetar stora resultatuppsättningar med hjälp av SQL Server-anslutningsåtgärderna.

Tidsgräns för exekvering av lagrad procedur

SQL Server-anslutningsappen har en åtgärd för att köra lagrad procedur med tidsgräns som är mindre än två minuter. Vissa lagrade procedurer kan ta längre tid än den här gränsen att slutföras, vilket orsakar ett 504-timeoutfel . Ibland kodas långvariga processer som lagrade procedurer uttryckligen för detta ändamål. På grund av tidsgränsen kan anrop av sådana procedurer från Azure Logic Apps skapa problem.

SQL Server-anslutningsåtgärderna stöder inte inbyggt asynkront läge. Om du vill kringgå den här begränsningen simulerar du det här läget med hjälp av följande objekt:

  • SQL-slutförandeutlösare
  • Intern SQL-direktfråga
  • Tillståndstabell
  • Jobb på serversidan

Anta till exempel att du har följande tidskrävande lagrade procedur. För att avsluta körningen överskrider processen tidsgränsen. Om du kör den här lagrade proceduren från ett arbetsflöde med hjälp av åtgärden SQL Server-anslutningsappen med namnet Kör lagrad procedur får du felet HTTP 504 Gateway Timeout .

CREATE PROCEDURE [dbo].[WaitForIt]
   @delay char(8) = '00:03:00'
AS
BEGIN
   SET NOCOUNT ON;
   WAITFOR DELAY @delay
END

I stället för att anropa den lagrade proceduren direkt kan du asynkront köra proceduren i bakgrunden med hjälp av en jobbagent. Du kan lagra indata och utdata i en tillståndstabell som du sedan kan komma åt och hantera via arbetsflödet. Om du inte behöver indata och utdata, eller om du redan skriver resultatet till en tabell i den lagrade proceduren, kan du förenkla den här metoden.

Viktigt!

Kontrollera att den lagrade proceduren och alla jobb är idempotent, vilket innebär att de kan köras flera gånger utan att påverka resultatet. Om den asynkrona bearbetningen misslyckas eller överskrider tidsgränsen kan jobbagenten försöka utföra den lagrade proceduren flera gånger igen. Innan du skapar några objekt och för att undvika duplicering av utdata kan du läsa de här metodtipsen och metoderna.

Om du vill köra proceduren asynkront i bakgrunden med jobbagenten för molnbaserad SQL Server följer du stegen för att skapa och använda Azure Elastic Job Agent för Azure SQL Database.

För lokal SQL Server och Azure SQL Managed Instance skapar och använder du SQL Server-agenten i stället. De grundläggande stegen är desamma som att konfigurera en jobbagent för Azure SQL Database.

Skapa jobbagent för Azure SQL Database

Skapa och använda Azure Elastic Job Agent för att skapa en jobbagent som kan köra lagrade procedurer för Azure SQL Database. Men innan du kan skapa den här jobbagenten måste du konfigurera behörigheter, grupper och mål enligt beskrivningen i dokumentationen för Azure Elastic Job Agent. Du måste också skapa en stödtillståndstabell i måldatabasen enligt beskrivningen i följande avsnitt.

Om du vill skapa jobbagenten utför du den här uppgiften i Azure-portalen. Den här metoden lägger till flera lagrade procedurer i databasen som används av agenten, även kallad agentdatabasen. Du kan sedan skapa en jobbagent som kör den lagrade proceduren i måldatabasen och fångar upp utdata när den är klar.

Skapa tillståndstabell för att registrera parametrar och lagra indata

SQL Agent-jobb accepterar inte indataparametrar. I måldatabasen skapar du i stället en tillståndstabell där du registrerar parametrarna och lagrar de indata som ska användas för att anropa dina lagrade procedurer. Alla agentjobbsteg körs mot måldatabasen, men jobbets lagrade procedurer körs mot agentdatabasen.

Använd det här schemat för att skapa tillståndstabellen:

CREATE TABLE [dbo].[LongRunningState](
   [jobid] [uniqueidentifier] NOT NULL,
   [rowversion] [timestamp] NULL,
   [parameters] [nvarchar](max) NULL,
   [start] [datetimeoffset](7) NULL,
   [complete] [datetimeoffset](7) NULL,
   [code] [int] NULL,
   [result] [nvarchar](max) NULL,
   CONSTRAINT [PK_LongRunningState] PRIMARY KEY CLUSTERED
      (   [jobid] ASC
      )WITH (STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF) ON [PRIMARY]
      ) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

Så här ser den resulterande tabellen ut i SQL Server Management Studio (SMSS):

Skärmbild som visar den skapade tillståndstabellen som lagrar indata för lagrad procedur.

För att säkerställa bra prestanda och se till att jobbagenten kan hitta den associerade posten använder tabellen jobbkörnings-ID :t (jobid) som primärnyckel. Om du vill kan du också lägga till enskilda kolumner för indataparametrarna. Det tidigare beskrivna schemat kan mer generellt hantera flera parametrar men begränsas till den storlek som beräknas av NVARCHAR(MAX) funktionen.

Skapa ett toppnivåjobb för att köra den lagrade proceduren

Om du vill köra den tidskrävande lagrade proceduren skapar du den här toppnivåjobbagenten i agentdatabasen:

EXEC jobs.sp_add_job 
   @job_name='LongRunningJob',
   @description='Execute Long-Running Stored Proc',
   @enabled = 1

Lägg till steg i jobbet som parameteriserar, kör och slutför den lagrade proceduren. Som standard överskrider ett jobbsteg tidsgränsen efter 12 timmar. Om den lagrade proceduren behöver mer tid, eller om du vill att proceduren ska överskrida tidsgränsen tidigare, kan du ändra parametern step_timeout_seconds till ett annat värde som anges i sekunder. Som standard har ett steg 10 inbyggda återförsök med en tidsgräns för backoff mellan varje nytt försök, vilket du kan använda till din fördel.

Här är stegen att lägga till:

  1. Vänta tills parametrarna visas i LongRunningState tabellen.

    Det här första steget väntar på att parametrarna ska läggas till i LongRunningState tabellen, vilket sker strax efter att jobbet startar. Om jobbkörnings-ID:t (jobid) inte läggs till i LongRunningState tabellen misslyckas bara steget. Standardinställningen för tidsgränsen för återförsök eller nedtrappning gör väntandet:

    EXEC jobs.sp_add_jobstep
       @job_name='LongRunningJob',
       @step_name= 'Parameterize WaitForIt',
       @step_timeout_seconds = 30,
       @command= N'
          IF NOT EXISTS(SELECT [jobid] FROM [dbo].[LongRunningState]
             WHERE jobid = $(job_execution_id))
             THROW 50400, ''Failed to locate call parameters (Step1)'', 1',
       @credential_name='JobRun',
       @target_group_name='DatabaseGroupLongRunning'
    
  2. Fråga parametrarna från tillståndstabellen och skicka dem till den lagrade proceduren. Det här steget kör även proceduren i bakgrunden.

    Om den lagrade proceduren inte behöver parametrar anropar du direkt den lagrade proceduren. Annars, för att skicka parametern @timespan, använd @callparams, som du också kan utöka för att skicka fler parametrar.

    EXEC jobs.sp_add_jobstep
       @job_name='LongRunningJob',
       @step_name='Execute WaitForIt',
       @command=N'
          DECLARE @timespan char(8)
          DECLARE @callparams NVARCHAR(MAX)
          SELECT @callparams = [parameters] FROM [dbo].[LongRunningState]
             WHERE jobid = $(job_execution_id)
          SET @timespan = @callparams
          EXECUTE [dbo].[WaitForIt] @delay = @timespan', 
       @credential_name='JobRun',
       @target_group_name='DatabaseGroupLongRunning'
    
  3. Slutför jobbet och registrera resultatet.

    EXEC jobs.sp_add_jobstep
       @job_name='LongRunningJob',
       @step_name='Complete WaitForIt',
       @command=N'
          UPDATE [dbo].[LongRunningState]
             SET [complete] = GETUTCDATE(),
                [code] = 200,
                [result] = ''Success''
             WHERE jobid = $(job_execution_id)',
       @credential_name='JobRun',
       @target_group_name='DatabaseGroupLongRunning'
    

Starta jobbet och skicka parametrarna

Starta jobbet genom att använda en intern direktfråga med åtgärden Kör en SQL-fråga och skicka omedelbart jobbets parametrar till tillståndstabellen. För att ange indata till jobid attributet i måltabellen lägger Azure Logic Apps till en För varje loop som itererar genom tabellutdata från föregående åtgärd. För varje jobbkörnings-ID kör du en Infoga radåtgärd som använder dynamiska datautdata med namnet ResultSets JobExecutionId för att lägga till parametrarna för jobbet för att packa upp och skicka till den lagrade målproceduren.

Skärmbild som visar åtgärden Infoga rad och föregående åtgärder i arbetsflödet.

När jobbet är klart uppdaterar jobbet LongRunningState-tabellen. Från ett annat arbetsflöde kan du utlösa resultatet med hjälp av utlösaren med namnet När ett objekt ändras. Om du inte behöver utdata, eller om du redan har en utlösare som övervakar en utdatatabell, kan du hoppa över den här delen.

Skärmbild som visar SQL-utlösaren för när ett objekt ändras.

Skapa jobbagent för SQL Server eller Azure SQL Managed Instance

För lokal SQL Server och Azure SQL Managed Instance skapar och använder du SQL Server-agenten. Jämfört med den molnbaserade jobbagenten för Azure SQL Database skiljer sig vissa hanteringsinformationer åt, men de grundläggande stegen är desamma.

Nästa steg