Azure SQL 数据库中的弹性作业
适用于:Azure SQL 数据库
在本文中,我们将回顾 Azure SQL 数据库中的弹性作业的功能和详细信息。
- 有关配置弹性作业的教程,请参阅弹性作业教程。
- 详细了解 Azure 数据库平台中的自动化概念。
弹性作业概述
可以创建和计划可针对一个或多个 Azure SQL 数据库定期执行的弹性作业,以运行 Transact-SQL (T-SQL) 查询和执行维护任务。
可以定义目标数据库或者要在其中执行作业的数据库组,同时定义作业的运行计划。 弹性作业中的所有日期和时间均为 UTC 时区。
作业可以处理登录到目标数据库的任务。 此外,可以定义、维护以及保存要跨一组数据库执行的 Transact-SQL 脚本。
每个作业会记录执行状态,如果发生任何失败,则还会自动重试操作。
何时使用弹性作业
弹性作业自动化有多种使用场景:
- 自动完成管理任务,并将作业计划为在每个工作日、数小时之后或按其他频率运行。
- 部署架构更改、凭据管理。
- 性能数据收集或租户(客户)遥测数据收集。
- 更新引用数据(所有数据库的公用信息)。
- 从 Azure Blob 存储加载数据。
- 配置作业,以便定期(例如,在非高峰时段)对一系列数据库执行作业。
- 持续将一组数据库中的查询结果收集到中央表中。
- 查询可以持续执行,并可配置为触发执行其他任务。
- 收集要报告的数据
- 将数据库集合中的数据聚合到单个目标表中。
- 对大量的数据库执行长时间运行的数据处理查询,例如,收集客户遥测数据。 结果将收集到单个目标表以供进一步分析。
- 数据移动
- 适用于自定义开发的解决方案、业务自动化或其他任务管理。
- 用于在数据库中的表之间提取/处理/插入数据的 ETL 处理。
在以下情况下考虑使用弹性作业:
- 需要按计划定期运行的任务,以一个或多个数据库为目标。
- 需要运行单次但跨多个数据库运行的任务。
- 需要针对数据库的任意组合运行作业:可以是一个或多个单独的数据库,可以是一个服务器上的所有数据库,可以是一个弹性池中的所有数据库,而且还可以灵活地包括或排除任何特定的数据库。 作业可以跨多个服务器、多个池来运行,甚至可以针对不同订阅中的数据库来运行。 服务器和池会在运行时进行动态枚举,因此作业会针对执行时目标组中存在的所有数据库来运行。
- 这是与 SQL 代理的显著区别,SQL 代理无法动态枚举目标数据库,尤其是在动态添加/删除数据库的 SaaS 客户场景中。
弹性作业组件
组件 | 说明 |
---|---|
弹性作业代理 | 为了运行和管理作业而创建的 Azure 资源。 |
作业数据库 | 作业代理用来存储作业相关数据、作业定义等内容的 Azure SQL 数据库中的数据库。 |
作业 | 作业是由一个或多个作业步骤组成的工作单元。 作业步骤指定要运行的 T-SQL 脚本,以及执行脚本所需的其他详细信息。 |
目标组 | 一组服务器、池和数据库,可对其运行作业。 |
弹性作业代理
弹性作业代理是用于创建、运行和管理作业的 Azure 资源。 弹性作业代理是在门户(也支持 PowerShell 和 REST API)中创建的 Azure 资源。
创建弹性作业代理需要现有的 Azure SQL 数据库中的数据库。 代理将这个现有的 Azure SQL 数据库配置为作业数据库。
可以通过 Azure 门户启动、禁用或取消作业。 通过 Azure 门户还可查看作业定义和执行历史记录。
弹性作业代理的成本
作业数据库的费率与任何 Azure SQL 数据库中的数据库一样。 有关弹性作业代理的成本,请参阅 Azure 定价计算器。
弹性作业数据库
作业数据库用于定义作业以及跟踪作业执行操作的状态和历史记录。 在目标数据库中执行作业。 作业数据库也用于存储代理元数据、日志、结果、作业定义,并且还包含许多有用的存储过程,以及其他数据库对象,可以通过 T-SQL 创建、运行和管理作业。
建议使用 Azure SQL 数据库(S1 或更高级别)来创建弹性作业代理。
作业数据库应该干净且为空,其服务目标应该为 S1 或更高的 Azure SQL 数据库。
作业数据库的服务对象建议使用 S1 或更高,但最佳选择取决于作业的性能需求:作业步骤数,作业目标数,以及作业的运行频率。
如果针对作业数据库的操作的速度比预期慢,则在出现速度缓慢的情况时使用 Azure 门户或 sys.dm_db_resource_stats DMV 监视作业数据库中的数据库性能和资源利用率。 如果资源(如 CPU、数据 IO 或日志写入)的使用率达到 100%,且与出现缓慢情况的时间段相关,请考虑以增量方式将数据库扩展到更高的服务目标(采用 DTU 模型或 vCore 模型),直到工作数据库性能得到充分改进。
重要
请勿修改现有对象或在作业数据库中创建新对象,但可以从表中读取报告和分析数据。
弹性作业和作业步骤
作业是按计划执行的或只执行一次的工作单元。 作业包含一个或多个作业步骤。
每个作业步骤都会指定一个要执行的 T-SQL 脚本、一个或多个要对其运行 T-SQL 脚本的目标组,以及作业代理连接到目标数据库所需的凭据。 每个作业步骤都有可自定义的超时和重试策略,并且可以选择性地指定输出参数。
弹性作业目标
使用弹性作业,可以按计划或按需跨大量数据库并行运行一个或多个 T-SQL 脚本。 目标可以是 Azure SQL 数据库的任何层。
可以针对数据库的任意组合运行计划作业:可以是一个或多个单独的数据库,可以是一个服务器上的所有数据库,可以是一个弹性池中的所有数据库,而且还可以灵活地包括或排除任何特定的数据库。 作业可以跨多个服务器、多个池来运行,甚至可以针对不同订阅中的数据库来运行。 服务器和池会在运行时进行动态枚举,因此作业会针对执行时目标组中存在的所有数据库来运行。
下图显示了一个跨不同类型的目标组执行作业的作业代理:
目标组
目标组定义可以在其上执行作业步骤的数据库集。 目标组可以包含任意数目和任意组合的以下项:
- SQL Server - 如果指定一个服务器,则在执行作业时存在于该服务器中的所有数据库都会成为组的一部分。 必须提供
master
数据库凭据,然后才能在执行作业之前枚举和更新组。 有关逻辑服务器的详细信息,请参阅 Azure SQL 数据库和 Azure Synapse Analytics 中的服务器是什么?。 - 弹性池 - 如果指定一个弹性池,则在执行作业时位于该弹性池中的所有数据库都会成为组的一部分。 就服务器来说,必须提供
master
数据库凭据,然后才能在执行作业之前更新组。 - 单个数据库 - 指定一个或多个将要成为组的一部分的单独数据库。
提示
在执行作业时,动态枚举会重新评估包含服务器或池的目标组中的数据库集。 动态枚举确保在执行作业时,作业可以跨服务器或池中存在的所有数据库运行。 在池或服务器成员身份更改频繁的情况下,在运行时重新评估数据库列表特别有用。
可以将池和单个数据库指定为包括在组中或从组中排除。 这样就可以使用任意数据库组合来创建目标组。 例如,可以向目标组添加一个服务器,但将弹性池中的特定数据库排除出去(也可以排除整个池)。
目标组可以包括多个区域的多个订阅中的数据库。 跨区域执行的延迟高于同一区域内的执行。
以下示例演示了如何在执行作业时动态枚举不同的目标组定义,以便确定作业要运行哪些数据库:
- 示例 1 演示的目标组包含一个由各个数据库组成的列表。 使用此目标组执行某个作业步骤时,作业步骤的操作会在这其中的每个数据库中执行。
- 示例 2 演示的目标组包含一个充当目标的服务器。 使用此目标组执行某个作业步骤时,会动态枚举服务器,以便确定目前在服务器中的数据库的列表。 作业步骤的操作会在这其中的每个数据库中执行。
- 示例 3 演示的目标组与示例 2 的类似,但明确排除了单个数据库。 作业步骤的操作不会在排除的数据库中执行。
- 示例 4 演示的目标组包含一个充当目标的弹性池。 与示例 2 类似,此池会在作业运行时动态枚举,以便确定池中数据库的列表。
- 示例 5 和示例 6 演示高级方案,其中的服务器、弹性池和数据库可以使用包括和排除规则进行组合。
注意
作业数据库本身可以是作业的目标。 在这种情况下,会像处理任何其他目标数据库一样处理作业数据库。 必须在作业数据库中创建作业用户并为其授予足够权限,并且该作业用户的数据库范围的凭据也必须存在于作业数据库中,就像任何其他目标数据库的情况一样。
身份验证
为弹性作业代理的所有目标选择一种方法。 例如,对于单个弹性作业代理,不能将一个目标服务器配置为使用数据库范围的凭据,而将另一个服务器配置为使用 Microsoft Entra ID 身份验证。
弹性作业代理可以通过两个身份验证选项连接到目标组指定的服务器/数据库:
通过用户分配的托管标识 (UMI) 进行身份验证
建议使用通过用户分配的托管标识 (UMI) 进行 Microsoft Entra(以前称为 Azure Active Directory)身份验证的选项,以便将弹性作业连接到 Azure SQL 数据库。 借助 Microsoft Entra ID 支持,作业代理将能够使用 UMI 连接到目标数据库(数据库、服务器、弹性池)和输出数据库。
或者,还可以在包含弹性作业数据库的逻辑服务器上启用 Microsoft Entra ID 身份验证,以便通过 Microsoft Entra ID 连接访问/查询该数据库。 但是,作业代理本身使用基于证书的内部身份验证来连接到其作业数据库。
可以创建一个 UMI,或使用现有的 UMI,并将相同的 UMI 分配给多个作业代理。 每个作业代理仅支持一个 UMI。 将 UMI 分配给作业代理后,该作业代理将仅使用此标识在目标数据库中连接和运行 t-SQL 作业。SQL 身份验证将不会用于该作业代理的目标服务器/数据库。
UMI 名称必须以字母或数字开头,长度介于 3 到 128 个字符之间。 可以包含 -
和 _
字符。
有关 Azure SQL 数据库 中的 UMI 的详细信息,请参阅 Azure SQL 的托管标识,包括使用 UMI 作为 Azure SQL 数据库逻辑服务器标识所需的步骤和优势。 有关详细信息,请参阅使用 Microsoft Entra(以前称为 Azure Active Directory)向 Azure SQL 平台进行身份验证。
重要
使用 Microsoft Entra ID 身份验证时,请在每个目标数据库中从该 Microsoft Entra ID 创建 jobuser
用户。 向用户授予在每个目标数据库中执行作业所需的权限。
不支持使用系统分配的托管标识 (SMI)。
通过数据库范围的凭据进行身份验证
虽然建议使用 Microsoft Entra(以前称为 Azure Active Directory)身份验证,但可以将作业配置为使用数据库范围的凭据,以便在执行时连接到目标组指定的数据库。 在 2023 年 10 月之前,数据库范围的凭据是唯一的身份验证选项。
如果目标组包含服务器或池,则可使用这些数据库范围的凭据连接到 master
数据库,以便枚举可用的数据库。
- 必须在作业数据库中创建数据库范围的凭据。
- 所有目标数据库必须有一个具有足够权限的登录名,否则作业无法成功完成(下图中的
jobuser
)。 - 在目标数据库中创建的凭据(下图中
masteruser
和jobuser
的LOGIN
和PASSWORD
)应与作业数据库所创建凭据中的IDENTITY
和SECRET
一致。 - 凭据可以跨作业反复使用,而凭据密码经过加密后,无法供只能通过只读方式访问作业对象的用户访问。
下图旨在帮助了解如何设置正确的作业凭据,以及弹性作业代理如何使用数据库凭据作为身份验证来连接到目标服务器/数据库中的登录名/用户。
注意
使用数据库范围的凭据时,请记得在每个目标数据库中创建 jobuser
用户。
弹性作业专用终结点
弹性作业代理支持弹性作业专用终结点。 通过创建弹性作业专用终结点,可建立弹性作业与目标服务器之间的专用链接。 弹性作业专用终结点的功能与 Azure 专用链接不同。
弹性作业专用终结点功能支持目标/输出服务器的专用连接,因此即使启用了“拒绝公共访问”选项,作业代理仍可进行连接。 如果你想要禁用“允许 Azure 服务和资源访问该服务器”选项,则使用专用终结点也是一种可行的解决方案。
弹性作业专用终结点支持弹性作业代理身份验证的所有选项。
弹性作业专用终结点功能允许选择服务托管的专用终结点,以在作业代理与其目标/输出服务器之间建立安全连接。 服务托管的专用终结点是特定虚拟网络和子网中的专用 IP 地址。 选择在其中一个作业代理的目标/输出服务器上使用专用终结点时,Microsoft 会创建服务托管的专用终结点。 然后,作业代理会独占使用此专用终结点来连接和执行作业,或用于在目标/输出数据库上写入作业输出。
可以通过 Azure 门户创建和允许弹性作业专用终结点。 通过专用链接连接的目标服务器可以位于 Azure 中的任何位置,即使在不同的地理位置和订阅中也是如此。 必须为每个所需的目标服务器和作业输出服务器创建专用终结点,才能启用此通信。
有关为弹性作业配置新的服务托管专用终结点的教程,请参阅配置 Azure SQL 弹性作业专用终结点。
弹性作业专用终结点的要求
- 若要使用弹性作业专用终结点,作业代理和目标服务器/数据库都必须托管在 Azure 中(相同或不同的区域)。
Microsoft.Network
资源提供程序必须注册作业代理和目标/输出服务器的主机订阅帐户。- 为每个目标/输出服务器创建弹性作业专用终结点。 必须先批准这些专用终结点,然后弹性作业代理才能使用它们。 可以通过该逻辑服务器或首选客户端的“网络”窗格来完成此操作。 然后,弹性作业代理将能够使用专用连接访问该服务器下的任何数据库。
- 从弹性作业代理到作业数据库的连接将不会使用专用终结点。 作业代理本身使用基于证书的内部身份验证来连接到其作业数据库。 需要注意的一种情况是,如果将作业数据库添加为目标组成员。 则其运行方式与常规目标数据库一样,此时请根据需要使用专用终结点进行设置。
弹性作业数据库权限
在创建作业代理期间,会在作业数据库中创建一个架构、多个表和一个名为 jobs_reader 的角色。 此角色使用以下权限创建,旨在为管理员提供进行作业监视所需的更细致访问控制。 管理员可以通过将用户添加到作业数据库中的 jobs_reader 角色,让用户能够监视作业的执行情况。
角色名称 | “作业”架构权限 | “jobs_internal”架构权限 |
---|---|---|
jobs_reader | SELECT | 无 |
注意
不得更新“作业数据库”中的内部目录视图,例如jobs.target_group_members。 手动更改上述目录视图可能会损坏“作业数据库”并导致失败。 上述视图仅用于只读查询。 可使用“作业数据库”中的存储过程来添加/删除目标组/成员,例如jobs.sp_add_target_group_member。
重要
在授予对“作业数据库”的提升访问权限之前,请考虑清楚安全隐患。 有权创建或编辑作业的恶意用户可能会创建或编辑一个作业,以便使用存储的凭据连接到受其控制的数据库,从而确定凭据的密码或执行恶意命令。
监视弹性作业
从 2023 年 10 月开始,弹性作业代理已与 Azure 警报集成以获得作业状态通知,从而简化了监视作业执行状态和历史记录的解决方案。
Azure 门户还有新的附加功能,用于支持弹性作业和作业监视。 在弹性作业代理的“概述”页上,将显示近期的作业执行,如以下屏幕截图所示。
可以使用 Azure 门户、Azure CLI、PowerShell 和 REST API 创建 Azure Monitor 警报规则。 失败的弹性作业指标是监视和接收有关弹性作业执行情况的警报的良好入手点。 此外,还可以选择通过 Azure 警报设施的可配置操作(如短信或电子邮件)发出警报。 有关详细信息,请参阅在 Azure 门户中为 Azure SQL 数据库创建警报。
有关示例,请参阅创建、配置和管理弹性作。
作业输出
针对每个目标数据库执行的作业步骤的结果会详细记录,而脚本输出则可捕获到指定的表中。 可以指定一个数据库,用于保存从作业返回的任何数据。
作业历史记录
通过查询表 jobs.job_executions
,在作业数据库中查看弹性作业执行历史记录。 系统清除作业会清除时间超过 45 天的执行历史记录。 若要手动删除时间不到 45 天的历史记录,请在作业数据库中执行 sp_purge_jobhistory
存储过程。
作业状态
可以通过查询表 jobs.job_executions
,在作业数据库中监视弹性作业执行情况。
最佳实践
使用弹性数据库作业时,请考虑以下最佳实践。
安全最佳做法
- 将 API 的使用限制为受信任的个人。
- 凭据应该具有执行作业步骤所需的最低权限。 有关详细信息,请参阅授权和权限。
- 使用服务器和/或池目标组成员时,强烈建议创建另外一个凭据,该凭据有权在
master
数据库上查看/列出数据库,用于在作业执行之前展开服务器和/或池的数据库列表。
弹性作业的性能
弹性作业在等待长时间运行的作业完成时使用极少的计算资源。
根据目标数据库组的大小和作业所需执行时间(并发辅助角色数)的不同,代理需要的计算量和作业数据库性能也会有所不同(目标数和作业数越多,所需计算量越大)。
并发容量层
从 2023 年 10 月开始,弹性作业代理具有多层性能,从而可以增加容量。
容量增量表示作业代理可以连接到和启动作业的并发目标数据库的总数。 如果执行作业时需要建立更多的并发目标连接,请从默认的 JA100 层(限制为 100 个并发目标连接)开始升级作业代理的层级。
在任何时候,大多数环境需要执行少于 100 个并发作业,因此默认设置为 JA100。
弹性作业代理层 | 最大并发作业数 |
---|---|
JA100 | 100 |
JA200 | 200 |
JA400 | 400 |
JA800 | 800 |
若超出作业代理的并发容量层和作业目标,将为某些目标数据库/服务器创建队列延迟。 例如,假设在 JA100 层中启动具有 110 个目标的作业,则有 10 个目标将会等到其他目标完成后才会开始。
可以通过 Azure 门户、PowerShell 或作业代理 REST API 修改弹性作业代理的层级或服务目标。 有关示例,请参阅调整作业代理。
限制对弹性池的作业影响
若要确保针对 Azure SQL 数据库弹性池中的数据库运行作业时资源不会超负荷,可以对作业进行配置,限制可以在同一时间对其运行作业的数据库数。
通过在 T-SQL 中设置 sp_add_jobstep
存储过程的 @max_parallelism
参数来设置作业运行时所在的并发数据库的数目。
幂等脚本
弹性作业的 T-SQL 脚本必须幂等。 幂等是指如果脚本成功,则再次运行时,会出现相同的结果。 脚本可能由于暂时性网络问题而失败。 在此情况下,作业会自动重试运行脚本,达到默认的次数才停止。 即使幂等脚本已成功运行两次(或更多次),也仍会返回相同的结果。
一个简单的策略是在创建对象之前测试其是否存在。 下面是一个假设的示例:
IF NOT EXISTS (SELECT * FROM sys.objects WHERE [name] = N'some_object')
print 'Object does not exist'
-- Create the object
ELSE
print 'Object exists'
-- If it exists, drop the object before recreating it.
同样地,脚本必须以逻辑方式测试并反驳它所找到的任何条件,才能成功执行。
限制
弹性作业服务目前存在以下限制。 我们正在尽一切努力消除其中的许多限制。
问题 | 说明 |
---|---|
故障转移/移动到新的 Azure 区域后,需要在新区域中重新创建和启动弹性作业代理。 | 弹性作业服务将其所有作业代理和作业元数据存储在作业数据库中。 Azure 资源的任何故障转移或移动到新的 Azure 区域也会将作业数据库、作业代理和作业元数据移动到新的 Azure 区域。 但是,弹性作业代理是仅计算资源,需要在新区域中显式重新创建和启动,然后作业才能在新区域中再次开始执行。 启动后,弹性作业代理将根据先前定义的作业计划继续在新区域中执行作业。 |
来自作业数据库的审核日志过多 | 弹性作业代理不断轮询作业数据库来检查新作业的采用和其他 CRUD 操作。 如果在作业数据库所在的服务器上启用审核,则作业数据库可能会生成大量的审核日志。 可以使用带有谓词表达式的 Set-AzSqlServerAudit 命令筛选掉这些审核日志,从而缓解该问题。例如: Set-AzSqlServerAudit -ResourceGroupName "ResourceGroup01" -ServerName "Server01" -BlobStorageTargetState Enabled -StorageAccountResourceId "/subscriptions/7fe3301d-31d3-4668-af5e-211a890ba6e3/resourceGroups/resourcegroup01/providers/Microsoft.Storage/storageAccounts/mystorage" -PredicateExpression "database_principal_name <> '##MS_JobAccount##'" 此命令只会筛选掉作业代理的作业数据库审核日志,而不是作业代理的任何目标数据库审核日志。 |
使用超大规模数据库作为作业数据库 | 不支持使用超大规模数据库作为作业数据库。 但是,弹性作业可将超大规模数据库用作目标,就如同将 Azure SQL 数据库中的任何其他数据库用作目标一样。 |
无服务器数据库和弹性作业的自动暂停。 | 不支持已启用自动暂停的无服务器数据库作为作业数据库。 弹性作业面向的无服务器数据库支持自动暂停,并将通过作业连接恢复。 |
将作业数据库导出到 BACPAC 文件 | 不支持将作业数据库导出到 BACPAC 文件。 如果需要导出包含作业数据库的 SQL 服务器,则应在导出服务器之前先删除作业数据库。 |