Azure SQL触发器使用 SQL change tracking 功能监视 SQL 表的更改,并在创建、更新或删除行时触发函数。 有关用于Azure SQL触发器的change tracking的配置详细信息,请参阅 设置 change tracking。 有关 Azure Functions Azure SQL 扩展的设置详细信息,请参阅 SQL 绑定概述。
Azure SQL触发Consumption 和 Premium 计划的缩放决策是通过基于目标的缩放完成的。 有关详细信息,请参阅基于Target 的缩放并查看Azure Functions托管选项。
注意
对消耗计划的支持需要 release v3.1.284 或更高版本Azure SQL绑定Azure Functions。
功能概述
Azure SQL触发器绑定使用轮询loop来检查更改,在检测到更改时触发用户函数。 概括而言,loop如下所示:
while (true) {
1. Get list of changes on table - up to a maximum number controlled by the Sql_Trigger_MaxBatchSize setting
2. Trigger function with list of changes
3. Wait for delay controlled by Sql_Trigger_PollingIntervalMs setting
}
更改始终按照执行顺序进行处理,首先处理最早的更改。 有关更改处理的几点注意事项:
- 如果一次更改多个行,则发送到函数的确切顺序取决于 CHANGETABLE 函数返回的顺序
- 一行的更改同时进行“批处理”。 如果对loop每次迭代之间的行进行了多次更改,则该行只存在一个更改条目,该行将显示上次处理状态与当前状态之间的差异
- 如果对一组行进行了更改,然后对其中一半相同的行进行了另一组更改,则将首先处理未进行第二次更改的那一半行。 这样的处理逻辑是由于上述说明以及正在批处理的更改 - 触发器只会看到所做的“最后”更改,并根据它们来确定处理顺序
注意
Azure SQL change tracking可以检测使用加密技术(例如Always Encrypted或Transparent Data Encryption(TDE)的表中的行级更改。 但是,Azure SQL触发器不会解密或公开更改有效负载中的加密列值。 触发器可以检测到发生了更改,但无法access这些列的解密数据。
有关change tracking以及如何由应用程序(如Azure SQL触发器)使用的详细信息,请参阅 使用 change tracking。
重要
为获得最佳安全性,应将Microsoft Entra ID与托管标识配合使用,以便在 Functions 与 Azure SQL Database 之间建立连接。 托管标识可以让应用更安全,因为不需在应用部署中存储机密,例如连接字符串、服务器名称、所使用端口中的凭据。 可以了解如何在本教程中使用托管标识,连接函数应用以使用托管标识和 SQL 绑定Azure SQL。
用法示例
GitHub 存储库提供了有关Azure SQL触发器的更多示例。
这些示例引用 ToDoItem 类和相应的数据库表:
namespace AzureSQL.ToDo
{
public class ToDoItem
{
public Guid Id { get; set; }
public int? order { get; set; }
public string title { get; set; }
public string url { get; set; }
public bool? completed { get; set; }
}
}
CREATE TABLE dbo.ToDo (
[Id] UNIQUEIDENTIFIER PRIMARY KEY,
[order] INT NULL,
[title] NVARCHAR(200) NOT NULL,
[url] NVARCHAR(200) NOT NULL,
[completed] BIT NOT NULL
);
Change tracking在数据库和表上启用:
ALTER DATABASE [SampleDatabase]
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);
ALTER TABLE [dbo].[ToDo]
ENABLE CHANGE_TRACKING;
SQL 触发器绑定到 IReadOnlyList<SqlChange<T>>,即 SqlChange 对象列表,每个对象具有 2 个属性:
-
项:已更改的项。 项的类型应遵循
ToDoItem类中所示的表架构。 -
操作:
SqlChangeOperation枚举中的值。 可能的值为Insert、Update和Delete。
using System;
using System.Collections.Generic;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Extensions.Sql;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
namespace AzureSQL.ToDo
{
public static class ToDoTrigger
{
[Function("ToDoTrigger")]
public static void Run(
[SqlTrigger("[dbo].[ToDo]", "SqlConnectionString")]
IReadOnlyList<SqlChange<ToDoItem>> changes,
FunctionContext context)
{
var logger = context.GetLogger("ToDoTrigger");
foreach (SqlChange<ToDoItem> change in changes)
{
ToDoItem toDoItem = change.Item;
logger.LogInformation($"Change operation: {change.Operation}");
logger.LogInformation($"Id: {toDoItem.Id}, Title: {toDoItem.title}, Url: {toDoItem.url}, Completed: {toDoItem.completed}");
}
}
}
}
用法示例
GitHub 存储库提供了有关Azure SQL触发器的更多示例。
该示例引用 ToDoItem 类、SqlChangeToDoItem 类、SqlChangeOperation 枚举和相应的数据库表:
在单独的 ToDoItem.java 文件中:
package com.function;
import java.util.UUID;
public class ToDoItem {
public UUID Id;
public int order;
public String title;
public String url;
public boolean completed;
public ToDoItem() {
}
public ToDoItem(UUID Id, int order, String title, String url, boolean completed) {
this.Id = Id;
this.order = order;
this.title = title;
this.url = url;
this.completed = completed;
}
}
在单独的 SqlChangeToDoItem.java 文件中:
package com.function;
public class SqlChangeToDoItem {
public ToDoItem item;
public SqlChangeOperation operation;
public SqlChangeToDoItem() {
}
public SqlChangeToDoItem(ToDoItem Item, SqlChangeOperation Operation) {
this.Item = Item;
this.Operation = Operation;
}
}
在单独的 SqlChangeOperation.java 文件中:
package com.function;
import com.google.gson.annotations.SerializedName;
public enum SqlChangeOperation {
@SerializedName("0")
Insert,
@SerializedName("1")
Update,
@SerializedName("2")
Delete;
}
CREATE TABLE dbo.ToDo (
[Id] UNIQUEIDENTIFIER PRIMARY KEY,
[order] INT NULL,
[title] NVARCHAR(200) NOT NULL,
[url] NVARCHAR(200) NOT NULL,
[completed] BIT NOT NULL
);
Change tracking在数据库和表上启用:
ALTER DATABASE [SampleDatabase]
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);
ALTER TABLE [dbo].[ToDo]
ENABLE CHANGE_TRACKING;
SQL 触发器绑定到 SqlChangeToDoItem[],即 SqlChangeToDoItem 对象数组,每个对象具有 2 个属性:
- 项:已更改的项。 项的类型应遵循
ToDoItem类中所示的表架构。 - 操作: 枚举中的值。 可能的值为
Insert、Update和Delete。
以下示例显示了在 ToDo 表发生更改时调用的 Java 函数:
package com.function;
import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.sql.annotation.SQLTrigger;
import com.function.Common.SqlChangeToDoItem;
import com.google.gson.Gson;
import java.util.logging.Level;
public class ProductsTrigger {
@FunctionName("ToDoTrigger")
public void run(
@SQLTrigger(
name = "todoItems",
tableName = "[dbo].[ToDo]",
connectionStringSetting = "SqlConnectionString")
SqlChangeToDoItem[] todoItems,
ExecutionContext context) {
context.getLogger().log(Level.INFO, "SQL Changes: " + new Gson().toJson(changes));
}
}
用法示例
GitHub 存储库提供了有关Azure SQL触发器的更多示例。
该示例引用 ToDoItem 数据库表:
CREATE TABLE dbo.ToDo (
[Id] UNIQUEIDENTIFIER PRIMARY KEY,
[order] INT NULL,
[title] NVARCHAR(200) NOT NULL,
[url] NVARCHAR(200) NOT NULL,
[completed] BIT NOT NULL
);
Change tracking在数据库和表上启用:
ALTER DATABASE [SampleDatabase]
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);
ALTER TABLE [dbo].[ToDo]
ENABLE CHANGE_TRACKING;
SQL 触发器绑定到 todoChanges,即对象列表,每个对象具有 2 个属性:
- 项:已更改的项。 项的结构将遵循表架构。
- 操作:可能的值为 、
Insert和Update。
以下示例显示了在 ToDo 表发生更改时调用的 PowerShell 函数。
下面是 function.json 文件中的绑定数据:
{
"name": "todoChanges",
"type": "sqlTrigger",
"direction": "in",
"tableName": "dbo.ToDo",
"connectionStringSetting": "SqlConnectionString"
}
配置部分解释了这些属性。
下面是 run.ps1 文件中的函数的示例 PowerShell 代码:
using namespace System.Net
param($todoChanges)
# The output is used to inspect the trigger binding parameter in test methods.
# Use -Compress to remove new lines and spaces for testing purposes.
$changesJson = $todoChanges | ConvertTo-Json -Compress
Write-Host "SQL Changes: $changesJson"
用法示例
GitHub 存储库提供了有关Azure SQL触发器的更多示例。
该示例引用 ToDoItem 数据库表:
CREATE TABLE dbo.ToDo (
[Id] UNIQUEIDENTIFIER PRIMARY KEY,
[order] INT NULL,
[title] NVARCHAR(200) NOT NULL,
[url] NVARCHAR(200) NOT NULL,
[completed] BIT NOT NULL
);
Change tracking在数据库和表上启用:
ALTER DATABASE [SampleDatabase]
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);
ALTER TABLE [dbo].[ToDo]
ENABLE CHANGE_TRACKING;
SQL 触发器绑定到 todoChanges,即对象数组,每个对象具有 2 个属性:
- 项:已更改的项。 项的结构将遵循表架构。
- 操作:可能的值为 、
Insert和Update。
以下示例显示了在 ToDo 表发生更改时调用的 JavaScript 函数。
下面是 function.json 文件中的绑定数据:
{
"name": "todoChanges",
"type": "sqlTrigger",
"direction": "in",
"tableName": "dbo.ToDo",
"connectionStringSetting": "SqlConnectionString"
}
配置部分解释了这些属性。
下面是 index.js 文件中的函数的示例 JavaScript 代码:
module.exports = async function (context, todoChanges) {
context.log(`SQL Changes: ${JSON.stringify(todoChanges)}`)
}
用法示例
GitHub 存储库提供了有关Azure SQL触发器的更多示例。
该示例引用 ToDoItem 数据库表:
CREATE TABLE dbo.ToDo (
[Id] UNIQUEIDENTIFIER PRIMARY KEY,
[order] INT NULL,
[title] NVARCHAR(200) NOT NULL,
[url] NVARCHAR(200) NOT NULL,
[completed] BIT NOT NULL
);
Change tracking在数据库和表上启用:
ALTER DATABASE [SampleDatabase]
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);
ALTER TABLE [dbo].[ToDo]
ENABLE CHANGE_TRACKING;
SQL 触发器绑定到变量 todoChanges,即对象列表,每个对象具有 2 个属性:
- 项:已更改的项。 项的结构将遵循表架构。
- 操作:可能的值为 、
Insert和Update。
以下示例显示了在 ToDo 表发生更改时调用的 Python 函数。
以下是 function_app.py 文件的示例 python 代码:
import json
import logging
import azure.functions as func
app = func.FunctionApp()
@app.function_name(name="ToDoTrigger")
@app.sql_trigger(arg_name="todo",
table_name="ToDo",
connection_string_setting="SqlConnectionString")
def todo_trigger(todo: str) -> None:
logging.info("SQL Changes: %s", json.loads(todo))
特性
C# 库使用 SqlTrigger 属性在函数上声明 SQL 触发器,该函数具有以下属性:
| Attribute 属性 | 说明 |
|---|---|
| TableName | 必需。 触发器监视的表的名称。 |
| ConnectionStringSetting | 必需。 包含数据库connection string的应用设置的名称,该设置包含受监视更改的表。 connection string设置名称对应于包含Azure SQL或SQL Server实例 |
| LeasesTableName | 可选。 用于存储租约的表的名称。 如果未指定,租约表名称将为 Leases_{FunctionId}_{TableId}。 here找到有关如何生成此信息的详细信息。 |
批注
在 Java 函数运行时库中,对值来自Azure SQL的参数使用 @SQLTrigger 注释(com.microsoft.azure.functions.sql.annotation.SQLTrigger)。 此批注支持以下元素:
| 元素 | 说明 |
|---|---|
| 名字 | 必需。 触发器绑定到的参数的名称。 |
| tableName | 必需。 触发器监视的表的名称。 |
| connectionStringSetting | 必需。 包含数据库connection string的应用设置的名称,该设置包含受监视更改的表。 connection string设置名称对应于包含Azure SQL或SQL Server实例 |
| LeasesTableName | 可选。 用于存储租约的表的名称。 如果未指定,租约表名称将为 Leases_{FunctionId}_{TableId}。 here找到有关如何生成此信息的详细信息。 |
配置
下表解释了在 function.json 文件中设置的绑定配置属性。
| “function.json”属性 | 说明 |
|---|---|
| 名字 | 必需。 触发器绑定到的参数的名称。 |
| type | 必需。 必须设置为 sqlTrigger。 |
| 方向 | 必需。 必须设置为 in。 |
| tableName | 必需。 触发器监视的表的名称。 |
| connectionStringSetting | 必需。 包含数据库connection string的应用设置的名称,该设置包含受监视更改的表。 connection string设置名称对应于包含Azure SQL或SQL Server实例 |
| LeasesTableName | 可选。 用于存储租约的表的名称。 如果未指定,租约表名称将为 Leases_{FunctionId}_{TableId}。 here找到有关如何生成此信息的详细信息。 |
可选配置
可以为用于本地开发的 SQL 触发器配置以下可选设置。
host.json
本部分介绍版本 2.x 及更高版本中此绑定可用的配置设置。 host.json 文件中的设置将应用于函数应用实例中的所有函数。 有关函数app configuration设置的详细信息,请参阅 host.json 参考Azure Functions。
| 设置 | 默认值 | 说明 |
|---|---|---|
| MaxBatchSize | 100 | 在发送到触发函数之前,在触发器每次迭代loop处理的最大更改数。 |
| PollingIntervalMs | 1000 | 处理每批更改之间的延迟(以毫秒为单位)。 (1000 毫秒为 1 秒) |
| MaxChangesPerWorker | 1000 | 每个 application-worker 允许的用户表中挂起的更改的数量上限。 如果更改计数超过此限制,则可能会导致横向扩展。此设置仅适用于启用了 runtime 驱动的缩放Azure函数应用。 |
示例 host.json 文件
下面是具有可选设置的 host.json 文件的示例:
{
"version": "2.0",
"extensions": {
"Sql": {
"MaxBatchSize": 300,
"PollingIntervalMs": 1000,
"MaxChangesPerWorker": 100
}
},
"logging": {
"applicationInsights": {
"samplingSettings": {
"isEnabled": true,
"excludedTypes": "Request"
}
},
"logLevel": {
"default": "Trace"
}
}
}
local.setting.json
local.settings.json 文件存储应用设置和本地开发工具使用的设置。 仅当在本地运行project时,才会使用 local.settings.json 文件中的设置。 将project发布到Azure时,请务必将任何必需的设置添加到函数应用的应用设置中。
重要
因为 local.settings.json 可能包含机密(如连接字符串),因此你绝不能将其存储在远程存储库中。 支持 Functions 的工具提供了将 local.settings.json 文件中的设置与部署project的函数应用中的 app 设置同步的方法。
| 设置 | 默认值 | 说明 |
|---|---|---|
| Sql_Trigger_BatchSize | 100 | 在发送到触发函数之前,在触发器每次迭代loop处理的最大更改数。 |
| Sql_Trigger_PollingIntervalMs | 1000 | 处理每批更改之间的延迟(以毫秒为单位)。 (1000 毫秒为 1 秒) |
| Sql_Trigger_MaxChangesPerWorker | 1000 | 每个 application-worker 允许的用户表中挂起的更改的数量上限。 如果更改计数超过此限制,则可能会导致横向扩展。此设置仅适用于启用了 runtime 驱动的缩放Azure函数应用。 |
示例 local.settings.json 文件
下面是具有可选设置的 local.settings.json 文件的示例:
{
"IsEncrypted": false,
"Values": {
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
"FUNCTIONS_WORKER_RUNTIME": "dotnet",
"SqlConnectionString": "",
"Sql_Trigger_MaxBatchSize": 300,
"Sql_Trigger_PollingIntervalMs": 1000,
"Sql_Trigger_MaxChangesPerWorker": 100
}
}
设置change tracking(必需)
设置change tracking以用于Azure SQL触发器需要执行两个步骤。 可以从支持运行查询的任何 SQL 工具完成这些步骤,包括 Visual Studio Code 或 SQL Server Management Studio。
在 SQL 数据库上启用change tracking,将
your database name替换为要监视的表所在的数据库的名称:ALTER DATABASE [your database name] SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);CHANGE_RETENTION选项指定保留change tracking信息(更改历史记录)的时间段。 SQL 数据库保留更改历史记录可能会影响触发器功能。 例如,如果 Azure 函数已关闭几天,然后恢复,则数据库将包含上述设置示例中过去两天内发生的更改。AUTO_CLEANUP选项用于启用或禁用删除旧change tracking信息的清理任务。 如果出现阻止触发器运行的临时问题,则可以关闭自动清理来暂停删除早于保留期的信息,直到问题得到解决。有关change tracking选项的详细信息,请参阅 SQL 文档。
对表启用change tracking,用要监视的表的名称替换
your table name(如果适用)更改架构):ALTER TABLE [dbo].[your table name] ENABLE CHANGE_TRACKING;触发器需要对要监视的表进行更改和对change tracking系统表的读取access。 每个函数触发器都有一个关联的change tracking表,并在架构
az_func租约表。 如果这些表尚不存在,则由触发器创建。 有关这些数据结构的详细信息,请参阅 Azure SQL 绑定库 documentation。
启用运行时驱动的缩放
根据需要,函数可以根据用户表中待处理的更改数自动缩放。 使用 SQL 触发器时,若要允许函数在高级计划上正确缩放,需要启用运行时缩放监视。
在 Azure portal 中,在函数应用中,选择 Configuration。
在 “函数运行时设置 ”选项卡上,对于 运行时缩放监视,请选择“ 打开”。
重试支持
GitHub存储库中提供了有关 SQL 触发器 重试支持和 leases 表的详细信息。
启动重试
如果启动过程中发生异常,则主机运行时会自动尝试采用指数退避策略重启触发器侦听器。 这样的重启会一直进行,直到侦听器成功启动或者启动被取消。
连接断开重试
如果函数成功启动,但发生错误导致连接断开(例如,服务器掉线)则函数会继续尝试和重新打开连接,直到函数停止或连接成功。 如果成功重新建立连接,则会继续处理中断时正在处理的更改。
请注意,这些重试位于 SqlClient 具有的内置空闲连接重试逻辑之外,可以使用 ConnectRetryCount 和 ConnectRetryIntervalconnection string 选项进行配置。 会先尝试内置的空闲连接重试,如果未能重新建立连接,然后触发器绑定再尝试自己重新建立连接。
函数异常重试
如果处理更改时用户函数中发生异常,则会在 60 秒内在当前正在处理的行批次进行重试。 重试期间,将其他更改作为正常进行处理,但当超时期限过后,会忽略该批次中导致异常发生的行。
如果给定行的函数执行连续失败 5 次,则会完全忽略未来对该行的所有更改。 由于批处理中的行不是确定性的,因此失败批处理中的行可能会在后续调用中以不同的批结尾。 这意味着,不是一定要忽略失败批次中的所有行。 如果该批次中的其他行导致发生异常,则“没有问题”的行最后会位于另一批次中,其在以后的调用中不会出现异常。
后续步骤
从数据库(输入绑定) - 将数据保存到数据库(输出绑定)