适用于:Azure 逻辑应用(消耗)
如果逻辑应用处理的结果集很大,导致
SQL 连接器
不会同时返回所有结果,或者如果你希望更好地控制结果集的大小和结构,则可以创建一个
存储过程
,按照想要的方式组织结果。 SQL 连接器提供了许多可以使用
Azure 逻辑应用
访问的后端功能,以便你更轻松地自动执行处理 SQL 数据库表的业务任务。
例如,获取或插入多个行时,逻辑应用可以在这些
限制
中使用
Until loop
来循环访问这些行。 但是,当逻辑应用必须处理数千或数百万行内容时,你希望将调用数据库的成本降到最低。 有关详细信息,请参阅
使用 SQL 连接器处理批量数据
。
存储过程执行的超时限制
SQL 连接器的存储过程超时限制是
小于 2 分钟
。 某些存储过程可能需要超过此限制才能完成,从而导致
504 Timeout
错误。 有时,出于此目的,这些长时间运行的进程被显式编码为存储过程。 由于超时限制,从 Azure 逻辑应用调用这些过程可能会出现问题。 尽管 SQL 连接器不本机支持异步模式,但你可以使用 SQL 完成触发器、本机 SQL 传递查询、状态表和服务器端作业来绕过此问题并模拟此模式。 对于此任务,可使用适用于
Azure SQL 数据库
的
Azure 弹性作业代理
。 对于
本地 SQL Server
和
Azure SQL 托管实例
,可使用
SQL Server 代理
。
例如,假设你有以下长时间运行的存储过程,完成运行需要的时间比超时限制长。 如果使用 SQL 连接器从逻辑应用运行此存储过程,则结果中会出现
HTTP 504 Gateway Timeout
错误。
CREATE PROCEDURE [dbo].[WaitForIt]
@delay char(8) = '00:03:00'
BEGIN
SET NOCOUNT ON;
WAITFOR DELAY @delay
可以使用作业代理在后台异步运行该过程,而不是直接调用存储过程。 可以将输入和输出存储在状态表中,然后可以通过逻辑应用与之交互。 如果不需要输入和输出,或者已经将结果写入存储过程中的表,则可以简化此方法。
请确保存储过程和所有作业都是幂等的,这意味着它们可以运行多次而不影响结果。
如果异步处理失败或超时,作业代理可能会多次重试该步骤,进而重试存储过程。 若要避免重复输出,请在创建任何对象之前,查看这些最佳做法和方法。
下一部分介绍如何使用 Azure SQL 数据库的 Azure 弹性作业代理。 对于 SQL Server 和 Azure SQL 托管实例,可以使用 SQL Server 代理。 某些管理详细信息会有所不同,但基本步骤与为 Azure SQL 数据库设置作业代理相同。
适用于 Azure SQL 数据库的作业代理
若要创建为 Azure SQL 数据库运行存储过程的作业,请使用 Azure 弹性作业代理。 在 Azure 门户中创建作业代理。 此方法将若干存储过程添加到代理使用的数据库(也称为代理数据库)。 然后,可以创建在目标数据库中运行存储过程并在完成后捕获输出的作业。
在创建作业之前,需要设置权限、组和目标,如 Azure 弹性作业代理的完整文档所述。 还需要在目标数据库中创建支持表,如以下部分所述。
SQL 代理作业不接受输入参数。 在目标数据库中,创建一个状态表,可以在其中注册参数并存储用于调用存储过程的输入。 所有代理作业步骤都针对目标数据库运行,但作业的存储过程针对代理数据库运行。
若要创建状态表,请使用此架构:
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]
SQL Server Management Studio (SMSS) 中的生成表如下所示:
为了确保良好的性能并确保代理作业可以找到关联的记录,该表使用作业执行 ID (jobid
) 作为主键。 如果需要,还可以为输入参数添加单个列。 前面描述的架构可以更普遍地处理多个参数,但仅限于由 NVARCHAR(MAX)
计算的大小。
创建用于运行存储过程的顶级作业
若要执行长时间运行的存储过程,请在代理数据库中创建此顶级作业代理:
EXEC jobs.sp_add_job
@job_name='LongRunningJob',
@description='Execute Long-Running Stored Proc',
@enabled = 1
现在,向参数化、运行和完成存储过程的作业添加步骤。 默认情况下,作业步骤将在 12 小时后超时。 如果存储过程需要更多时间,或者你希望该过程更早超时,可以将 step_timeout_seconds
参数更改为以秒为单位指定的另一个值。 默认情况下,一个步骤具有 10 个内置重试,每次重试之间有回退超时,你可以加以利用。
以下是要添加的步骤:
等待参数出现在 LongRunningState
表中。
第一步等待参数添加到 LongRunningState
表中,这会在作业开始后不久发生。 如果未将作业执行 ID (jobid
) 添加到 LongRunningState
表,则步骤将仅失败,并且默认重试或回退超时将等待:
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'
从状态表中查询参数,然后将它们传递给存储过程。 此步骤还会在后台运行该过程。
如果存储过程不需要参数,只需直接调用存储过程。 否则,若要传递 @timespan
参数,请使用 @callparams
,也可将其扩展以传递其他参数。
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'
完成该作业并记录结果。
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'
启动作业并传递参数
若要启动作业,请将传递本机查询和“执行 SQL 查询”操作结合使用,并立即将作业的参数推送到状态表中。 为了向目标表中的 jobid
属性提供输入,逻辑应用添加了一个 For each 循环,该循环从前面的操作中循环访问表输出。 对于每个作业执行 ID,运行一个“插入行”操作,该操作使用动态数据输出 ResultSets JobExecutionId
添加作业的参数以解包并传递给目标存储过程。
当作业完成时,作业将更新 LongRunningState
表,以便你可以使用“当修改项时”触发器来轻松对结果进行触发。 如果不需要输出,或者已有监视输出表的触发器,则可以跳过此部分。
SQL Server 或 Azure SQL 托管实例的作业代理
对于同一场景,可以将 SQL Server 代理用于本地 SQL Server 和 Azure SQL 托管实例。 尽管某些管理详细信息会有所不同,但基本步骤与为 Azure SQL 数据库设置作业代理相同。
连接到 SQL Server、Azure SQL 数据库或 Azure SQL 托管实例