适用于 Functions 的 Azure SQL 触发器
Azure SQL 触发器使用 SQL 更改跟踪功能来监视 SQL 表的更改,并在创建、更新或删除行时触发函数。 有关用于 Azure SQL 触发器的更改跟踪的配置详细信息,请参阅设置更改跟踪。 有关 Azure Functions 的 Azure SQL 扩展的设置详细信息,请参阅 SQL 绑定概述。
面向消耗计划和高级计划的 Azure SQL 触发器缩放决策是通过基于目标的缩放完成的。 有关详细信息,请参阅基于目标的缩放。
功能概述
Azure SQL 触发器绑定使用轮询循环来检查是否有更改,并在检测到更改时触发用户函数。 在高级别,循环如下所示:
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 函数返回的顺序
- 一行的更改同时进行“批处理”。 如果在循环的每次迭代之间对一行进行了多次更改,那么该行将只存在一个更改条目,将会显示上次处理状态和当前状态之间的差异
- 如果对一组行进行了更改,然后对其中一半相同的行进行了另一组更改,则将首先处理未进行第二次更改的那一半行。 这样的处理逻辑是由于上述说明以及正在批处理的更改 - 触发器只会看到所做的“最后”更改,并根据它们来确定处理顺序
有关更改跟踪以及应用程序(如 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
);
数据库和表中启用了更改跟踪:
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
。
以下示例显示了在 ToDo
表发生更改时调用的 C# 函数:
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
);
数据库和表中启用了更改跟踪:
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
类中所示的表架构。 - 操作:
SqlChangeOperation
枚举中的值。 可能的值为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
);
数据库和表中启用了更改跟踪:
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
和Delete
。
以下示例显示了在 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
);
数据库和表中启用了更改跟踪:
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
和Delete
。
以下示例显示了在 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
);
数据库和表中启用了更改跟踪:
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
和Delete
。
以下示例显示了在 ToDo
表发生更改时调用的 Python 函数。
以下是 function_app.py 文件的示例 python 代码:
import json
import logging
import azure.functions as func
from azure.functions.decorators.core import DataType
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 | 必需。 应用设置的名称,其中包含数据库的连接字符串,该数据库包含被监视更改的表。 连接字符串设置名称对应于应用程序设置(本地开发为 local.settings.json ),其中包含 Azure SQL 或 SQL Server 实例的连接字符串。 |
LeasesTableName | 可选。 用于存储租约的表的名称。 如果未指定,租约表名称将为 Leases_{FunctionId}_{TableId}。 可在此处找到有关如何生成此信息的详细信息。 |
批注
在 Java 函数运行时库中,对其值来自 Azure SQL 的参数使用 @SQLTrigger
注释 (com.microsoft.azure.functions.sql.annotation.SQLTrigger
)。 此批注支持以下元素:
元素 | 说明 |
---|---|
name | 必需。 触发器绑定到的参数的名称。 |
tableName | 必需。 触发器监视的表的名称。 |
connectionStringSetting | 必需。 应用设置的名称,其中包含数据库的连接字符串,该数据库包含被监视更改的表。 连接字符串设置名称对应于应用程序设置(本地开发为 local.settings.json ),其中包含 Azure SQL 或 SQL Server 实例的连接字符串。 |
LeasesTableName | 可选。 用于存储租约的表的名称。 如果未指定,租约表名称将为 Leases_{FunctionId}_{TableId}。 可在此处找到有关如何生成此信息的详细信息。 |
配置
下表解释了在 function.json 文件中设置的绑定配置属性。
“function.json”属性 | 说明 |
---|---|
name | 必需。 触发器绑定到的参数的名称。 |
type | 必需。 必须设置为 sqlTrigger 。 |
direction | 必需。 必须设置为 in 。 |
tableName | 必需。 触发器监视的表的名称。 |
connectionStringSetting | 必需。 应用设置的名称,其中包含数据库的连接字符串,该数据库包含被监视更改的表。 连接字符串设置名称对应于应用程序设置(本地开发为 local.settings.json ),其中包含 Azure SQL 或 SQL Server 实例的连接字符串。 |
LeasesTableName | 可选。 用于存储租约的表的名称。 如果未指定,租约表名称将为 Leases_{FunctionId}_{TableId}。 可在此处找到有关如何生成此信息的详细信息。 |
可选配置
可以为用于本地开发的 SQL 触发器配置以下可选设置。
host.json
本部分介绍版本 2.x 及更高版本中可用于此绑定的配置设置。 host.json 文件中的设置将应用于函数应用实例中的所有函数。 下面的示例 host.json 文件仅包含此绑定的 2.x 版及更高版本设置。 若要详细了解版本 2.x 及更高版本中的函数应用程序配置设置,请参阅 Azure Functions 的 host.json 参考。
设置 | 默认值 | 说明 |
---|---|---|
MaxBatchSize | 100 | 在发送到触发函数之前,使用触发器循环的每次迭代处理的最大更改数。 |
PollingIntervalMs | 1000 | 处理每批更改之间的延迟(以毫秒为单位)。 (1000 毫秒为 1 秒) |
MaxChangesPerWorker | 1000 | 每个 application-worker 允许的用户表中挂起的更改的数量上限。 如果更改的计数超过此限制,则可能会导致横向扩展。此设置仅适用于启用了运行时驱动缩放的 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 文件存储应用设置和本地开发工具使用的设置。 只有在本地运行项目时,才会使用 local.settings.json 文件中的设置。 将项目发布到 Azure 时,请务必将任何必需的设置添加到函数应用的应用设置。
重要
因为 local.settings.json 可能包含机密(如连接字符串),因此你绝不能将其存储在远程存储库中。 支持 Functions 的工具提供了将 local.settings.json 文件中的设置与部署你的项目的函数应用中的应用设置同步的方法。
设置 | 默认值 | 说明 |
---|---|---|
Sql_Trigger_BatchSize | 100 | 在发送到触发函数之前,使用触发器循环的每次迭代处理的最大更改数。 |
Sql_Trigger_PollingIntervalMs | 1000 | 处理每批更改之间的延迟(以毫秒为单位)。 (1000 毫秒为 1 秒) |
Sql_Trigger_MaxChangesPerWorker | 1000 | 每个 application-worker 允许的用户表中挂起的更改的数量上限。 如果更改的计数超过此限制,则可能会导致横向扩展。此设置仅适用于启用了运行时驱动缩放的 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
}
}
设置更改跟踪(必需)
设置用于 Azure SQL 触发器的更改跟踪需要执行两个步骤。 可以通过任何支持运行查询的 SQL 工具完成这两个操作,包括 Visual Studio Code、Azure Data Studio 或 SQL Server Management Studio。
在 SQL 数据库上启用更改跟踪,并将
your database name
替换为要监视的表所在的数据库的名称:ALTER DATABASE [your database name] SET CHANGE_TRACKING = ON (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);
CHANGE_RETENTION
选项指定了更改跟踪信息(更改历史记录)的保留时间。 SQL 数据库保留更改历史记录可能会影响触发器功能。 例如,如果 Azure Function 关闭数天然后恢复,则数据库会包含上述设置示例中过去两天进行的更改。可使用
AUTO_CLEANUP
选项来启用或禁用删除陈旧的更改跟踪信息的清除任务。 如果出现阻止触发器运行的临时问题,则可以关闭自动清理来暂停删除早于保留期的信息,直到问题得到解决。SQL 文档中提供了有关更改跟踪选项的详细信息。
在表中启用更改跟踪,并将
your table name
替换为要监视的表的名称(如果合适,更改架构):ALTER TABLE [dbo].[your table name] ENABLE CHANGE_TRACKING;
触发器需要对被监视更改的表和更改跟踪系统表具有读取访问权限。 每个函数触发器都有一个关联更改跟踪,并租用架构
az_func
中的表。 如果这些表尚不存在,则由触发器创建。 Azure SQL 绑定库文档中提供了有关这些数据结构的详细信息。
启用运行时驱动的缩放
根据需要,函数可以根据用户表中待处理的更改数自动缩放。 使用 SQL 触发器时,若要允许函数在高级计划上正确缩放,需要启用运行时缩放监视。
重试支持
如需详细了解 GitHub 仓库中提供的 SQL 触发器重试支持和租用表。
启动重试
如果启动过程中发生异常,则主机运行时会自动尝试采用指数退避策略重启触发器侦听器。 这样的重启会一直进行,直到侦听器成功启动或者启动被取消。
连接断开重试
如果函数成功启动,但发生错误导致连接断开(例如,服务器掉线)则函数会继续尝试和重新打开连接,直到函数停止或连接成功。 如果成功重新建立连接,则会继续处理中断时正在处理的更改。
请注意,这些重试位于 SqlClient 具有的内置空闲连接重试逻辑之外,可以使用 ConnectRetryCount
和 ConnectRetryInterval
连接字符串选项进行配置。 会先尝试内置的空闲连接重试,如果未能重新建立连接,然后触发器绑定再尝试自己重新建立连接。
函数异常重试
如果处理更改时用户函数中发生异常,则会在 60 秒内在当前正在处理的行批次进行重试。 重试期间,将其他更改作为正常进行处理,但当超时期限过后,会忽略该批次中导致异常发生的行。
如果给定行的函数执行连续失败 5 次,则会完全忽略未来对该行的所有更改。 由于某一批次中的行具有不确定性,因此失败批次中的行最后可能会位于后续调用中的其他批次中。 这意味着,不是一定要忽略失败批次中的所有行。 如果该批次中的其他行导致发生异常,则“没有问题”的行最后会位于另一批次中,其在以后的调用中不会出现异常。