Trigger SQL di Azure per Funzioni

Nota

Nelle funzioni del piano a consumo il ridimensionamento automatico non è supportato per il trigger SQL. Se il processo di ridimensionamento automatico arresta la funzione, l'elaborazione degli eventi verrà arrestata e dovrà essere riavviata manualmente.

Usare piani Premium o dedicati per la scalabilità dei vantaggi con il trigger SQL.

Il trigger SQL di Azure usa la funzionalità di rilevamento delle modifiche SQL per monitorare una tabella SQL per rilevare le modifiche e attivare una funzione quando viene creata, aggiornata o eliminata una riga. Per informazioni dettagliate sulla configurazione per il rilevamento delle modifiche da usare con il trigger SQL di Azure, vedere Configurare il rilevamento delle modifiche. Per informazioni dettagliate sull'installazione dell'estensione SQL di Azure per Funzioni di Azure, vedere la panoramica dell'associazione SQL.

Le decisioni di ridimensionamento dei trigger sql di Azure per i piani a consumo e Premium vengono eseguite tramite il ridimensionamento basato sulla destinazione. Per altre informazioni, vedere Scalabilità basata su destinazione.

Panoramica delle funzionalità

L'associazione di trigger SQL di Azure usa un ciclo di polling per verificare la presenza di modifiche, attivando la funzione utente quando vengono rilevate modifiche. A livello generale, il ciclo è simile al seguente:

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
}

Le modifiche vengono elaborate nell'ordine in cui sono state apportate le modifiche, con le modifiche meno recenti elaborate per prime. Un paio di note sull'elaborazione delle modifiche:

  1. Se le modifiche a più righe vengono apportate contemporaneamente all'ordine esatto in cui vengono inviate alla funzione si basa sull'ordine restituito dalla funzione CHANGETABLE
  2. Le modifiche vengono "raggruppate" per una riga. Se vengono apportate più modifiche a una riga tra ogni iterazione del ciclo, esiste solo una singola voce di modifica per tale riga che mostrerà la differenza tra l'ultimo stato elaborato e lo stato corrente
  3. Se vengono apportate modifiche a un set di righe e quindi viene apportato un altro set di modifiche alla metà delle stesse righe, la metà delle righe che non sono state modificate una seconda volta viene elaborata per prima. Questa logica di elaborazione è dovuta alla nota precedente con le modifiche in batch. Il trigger visualizzerà solo l'ultima modifica apportata e lo userà per l'ordine in cui li elabora.

Per altre informazioni sul rilevamento delle modifiche e sul modo in cui viene usato da applicazioni come i trigger SQL di Azure, vedere Usare il rilevamento delle modifiche.

Esempio di utilizzo

Altri esempi per il trigger SQL di Azure sono disponibili nel repository GitHub.

L'esempio fa riferimento a una ToDoItem classe e a una tabella di database corrispondente:

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
);

Il rilevamento delle modifiche è abilitato nel database e nella tabella:

ALTER DATABASE [SampleDatabase]
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);

ALTER TABLE [dbo].[ToDo]
ENABLE CHANGE_TRACKING;

Il trigger SQL viene associato a un IReadOnlyList<SqlChange<T>>oggetto , un elenco di SqlChange oggetti ognuno con due proprietà:

  • Elemento: l'elemento modificato. Il tipo dell'elemento deve seguire lo schema della tabella come illustrato nella ToDoItem classe .
  • Operazione: valore di SqlChangeOperation enumerazione. I valori possibili sono Insert, Update e Delete.

L'esempio seguente mostra una funzione C# richiamata quando sono presenti modifiche alla ToDo tabella:

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}");
            }
        }
    }
}

Esempio di utilizzo

Altri esempi per il trigger SQL di Azure sono disponibili nel repository GitHub.

L'esempio fa riferimento a una ToDoItem classe, a una SqlChangeToDoItem classe, a un'enumerazione SqlChangeOperation e a una tabella di database corrispondente:

In un file ToDoItem.javaseparato :

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;
    }
}

In un file SqlChangeToDoItem.javaseparato :

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;
    }
}

In un file SqlChangeOperation.javaseparato :

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
);

Il rilevamento delle modifiche è abilitato nel database e nella tabella:

ALTER DATABASE [SampleDatabase]
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);

ALTER TABLE [dbo].[ToDo]
ENABLE CHANGE_TRACKING;

Il trigger SQL viene associato a un oggetto SqlChangeToDoItem[], una matrice di SqlChangeToDoItem oggetti ognuno con due proprietà:

  • item: l'elemento modificato. Il tipo dell'elemento deve seguire lo schema della tabella come illustrato nella ToDoItem classe .
  • operation: valore di SqlChangeOperation enumerazione. I valori possibili sono Insert, Update e Delete.

L'esempio seguente mostra una funzione Java richiamata quando sono presenti modifiche alla ToDo tabella:

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));
    }
}

Esempio di utilizzo

Altri esempi per il trigger SQL di Azure sono disponibili nel repository GitHub.

L'esempio fa riferimento a una ToDoItem tabella di database:

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
);

Il rilevamento delle modifiche è abilitato nel database e nella tabella:

ALTER DATABASE [SampleDatabase]
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);

ALTER TABLE [dbo].[ToDo]
ENABLE CHANGE_TRACKING;

Il trigger SQL viene associato a todoChanges, un elenco di oggetti ognuno con due proprietà:

  • item: l'elemento modificato. La struttura dell'elemento seguirà lo schema della tabella.
  • operation: i valori possibili sono Insert, Updatee Delete.

L'esempio seguente mostra una funzione di PowerShell richiamata quando sono presenti modifiche alla ToDo tabella.

Di seguito sono riportati i dati di associazione nel file function.json:

{
    "name": "todoChanges",
    "type": "sqlTrigger",
    "direction": "in",
    "tableName": "dbo.ToDo",
    "connectionStringSetting": "SqlConnectionString"
}

Queste proprietà sono descritte nella sezione configuration.

Di seguito è riportato il codice di PowerShell di esempio per la funzione nel run.ps1 file :

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"

Esempio di utilizzo

Altri esempi per il trigger SQL di Azure sono disponibili nel repository GitHub.

L'esempio fa riferimento a una ToDoItem tabella di database:

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
);

Il rilevamento delle modifiche è abilitato nel database e nella tabella:

ALTER DATABASE [SampleDatabase]
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);

ALTER TABLE [dbo].[ToDo]
ENABLE CHANGE_TRACKING;

Il trigger SQL associa todoChanges, una matrice di oggetti ognuno con due proprietà:

  • item: l'elemento modificato. La struttura dell'elemento seguirà lo schema della tabella.
  • operation: i valori possibili sono Insert, Updatee Delete.

L'esempio seguente mostra una funzione JavaScript richiamata quando sono presenti modifiche alla ToDo tabella.

Di seguito sono riportati i dati di associazione nel file function.json:

{
    "name": "todoChanges",
    "type": "sqlTrigger",
    "direction": "in",
    "tableName": "dbo.ToDo",
    "connectionStringSetting": "SqlConnectionString"
}

Queste proprietà sono descritte nella sezione configuration.

Di seguito è riportato il codice JavaScript di esempio per la funzione nel index.js file :

module.exports = async function (context, todoChanges) {
    context.log(`SQL Changes: ${JSON.stringify(todoChanges)}`)
}

Esempio di utilizzo

Altri esempi per il trigger SQL di Azure sono disponibili nel repository GitHub.

L'esempio fa riferimento a una ToDoItem tabella di database:

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
);

Il rilevamento delle modifiche è abilitato nel database e nella tabella:

ALTER DATABASE [SampleDatabase]
SET CHANGE_TRACKING = ON
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);

ALTER TABLE [dbo].[ToDo]
ENABLE CHANGE_TRACKING;

Il trigger SQL viene associato a una variabile todoChanges, un elenco di oggetti ognuno con due proprietà:

  • item: l'elemento modificato. La struttura dell'elemento seguirà lo schema della tabella.
  • operation: i valori possibili sono Insert, Updatee Delete.

Nell'esempio seguente viene illustrata una funzione Python richiamata quando vengono apportate modifiche alla ToDo tabella.

Di seguito sono riportati i dati di associazione nel file function.json:

{
    "name": "todoChanges",
    "type": "sqlTrigger",
    "direction": "in",
    "tableName": "dbo.ToDo",
    "connectionStringSetting": "SqlConnectionString"
}

Queste proprietà sono descritte nella sezione configuration.

Di seguito è riportato il codice Python di esempio per la funzione nel __init__.py file :

import json
import logging

def main(changes):
    logging.info("SQL Changes: %s", json.loads(changes))

Attributi

La libreria C# usa l'attributo SqlTrigger per dichiarare il trigger SQL nella funzione, con le proprietà seguenti:

Proprietà dell'attributo Descrizione
TableName Obbligatorio. Nome della tabella monitorata dal trigger.
ConnectionStringSetting Obbligatorio. Nome di un'impostazione dell'app che contiene il stringa di connessione per il database contenente la tabella monitorata per le modifiche. Il nome dell'impostazione stringa di connessione corrisponde all'impostazione dell'applicazione (in local.settings.json per lo sviluppo locale) che contiene il stringa di connessione all'istanza di SQL o SQL Server di Azure.
LeasesTableName Facoltativo. Nome della tabella utilizzata per archiviare i lease. Se non specificato, il nome della tabella lease verrà Leases_{FunctionId}_{TableId}. Altre informazioni su come viene generato sono disponibili qui.

Annotazioni

Nella libreria di runtime delle funzioni Java usare l'annotazione @SQLTrigger (com.microsoft.azure.functions.sql.annotation.SQLTrigger) nei parametri il cui valore proviene da Azure SQL. Questa annotazione supporta gli elementi seguenti:

Elemento Descrizione
name Obbligatorio. Nome del parametro a cui viene associato il trigger.
tableName Obbligatorio. Nome della tabella monitorata dal trigger.
connectionStringSetting Obbligatorio. Nome di un'impostazione dell'app che contiene il stringa di connessione per il database contenente la tabella monitorata per le modifiche. Il nome dell'impostazione stringa di connessione corrisponde all'impostazione dell'applicazione (in local.settings.json per lo sviluppo locale) che contiene il stringa di connessione all'istanza di SQL o SQL Server di Azure.
LeasesTableName Facoltativo. Nome della tabella utilizzata per archiviare i lease. Se non specificato, il nome della tabella lease verrà Leases_{FunctionId}_{TableId}. Altre informazioni su come viene generato sono disponibili qui.

Impostazione

Nella tabella seguente sono illustrate le proprietà di configurazione dell'associazione impostate nel file function.json.

Proprietà di function.json Descrizione
name Obbligatorio. Nome del parametro a cui viene associato il trigger.
type Obbligatorio. Deve essere impostato su sqlTrigger.
direction Obbligatorio. Deve essere impostato su in.
tableName Obbligatorio. Nome della tabella monitorata dal trigger.
connectionStringSetting Obbligatorio. Nome di un'impostazione dell'app che contiene il stringa di connessione per il database contenente la tabella monitorata per le modifiche. Il nome dell'impostazione stringa di connessione corrisponde all'impostazione dell'applicazione (in local.settings.json per lo sviluppo locale) che contiene il stringa di connessione all'istanza di SQL o SQL Server di Azure.
LeasesTableName Facoltativo. Nome della tabella utilizzata per archiviare i lease. Se non specificato, il nome della tabella lease verrà Leases_{FunctionId}_{TableId}. Altre informazioni su come viene generato sono disponibili qui.

Configurazione facoltativa

Per il trigger SQL è possibile configurare le impostazioni facoltative seguenti:

Questa sezione descrive le impostazioni di configurazione disponibili per questa associazione nelle versioni 2.x e successive. Impostazioni nel file host.json si applicano a tutte le funzioni in un'istanza dell'app per le funzioni. L'esempio host.json file seguente contiene solo le impostazioni della versione 2.x+ per questa associazione. Per altre informazioni sulle impostazioni di configurazione delle app per le funzioni nelle versioni 2.x e successive, vedere informazioni di riferimento host.json per Funzioni di Azure.

Impostazione Descrizione
Sql_Trigger_BatchSize Numero massimo di modifiche elaborate con ogni iterazione del ciclo di trigger prima di essere inviate alla funzione attivata. Il valore predefinito è 100.
Sql_Trigger_PollingIntervalMs Ritardo in millisecondi tra l'elaborazione di ogni batch di modifiche. Il valore predefinito è 1000 (1 secondo).
Sql_Trigger_MaxChangesPerWorker Limite massimo per il numero di modifiche in sospeso nella tabella utente consentite per ogni ruolo di lavoro dell'applicazione. Se il numero di modifiche supera questo limite, potrebbe comportare un aumento del numero di istanze. L'impostazione si applica solo alle app per le funzioni di Azure con scalabilità guidata dal runtime abilitata. Il valore predefinito è 1000.

Configurare il rilevamento delle modifiche (obbligatorio)

La configurazione del rilevamento delle modifiche da usare con il trigger SQL di Azure richiede due passaggi. Questi passaggi possono essere completati da qualsiasi strumento SQL che supporta l'esecuzione di query, tra cui Visual Studio Code, Azure Data Studio o SQL Server Management Studio.

  1. Abilitare il rilevamento delle modifiche nel database SQL, sostituendo your database name con il nome del database in cui si trova la tabella da monitorare:

    ALTER DATABASE [your database name]
    SET CHANGE_TRACKING = ON
    (CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);
    

    L'opzione CHANGE_RETENTION specifica il periodo di tempo per il quale vengono mantenute le informazioni di rilevamento delle modifiche (cronologia modifiche). La conservazione della cronologia delle modifiche da parte del database SQL potrebbe influire sulla funzionalità dei trigger. Ad esempio, se la funzione di Azure è disattivata per diversi giorni e quindi ripresa, il database conterrà le modifiche apportate negli ultimi due giorni nell'esempio di configurazione precedente.

    L'opzione AUTO_CLEANUP viene usata per abilitare o disabilitare l'attività di pulizia che rimuove le informazioni di rilevamento delle modifiche precedenti. Se un problema temporaneo che impedisce l'esecuzione del trigger, disattivare la pulizia automatica può essere utile per sospendere la rimozione delle informazioni precedenti al periodo di conservazione fino a quando il problema non viene risolto.

    Altre informazioni sulle opzioni di rilevamento delle modifiche sono disponibili nella documentazione di SQL.

  2. Abilitare il rilevamento delle modifiche nella tabella, sostituendo your table name con il nome della tabella da monitorare (modificando lo schema, se appropriato):

    ALTER TABLE [dbo].[your table name]
    ENABLE CHANGE_TRACKING;
    

    Il trigger deve avere accesso in lettura alla tabella monitorata per le modifiche e alle tabelle di sistema di rilevamento delle modifiche. Ogni trigger di funzione ha una tabella di rilevamento delle modifiche associata e una tabella lease in uno schema az_func. Queste tabelle vengono create dal trigger se non esistono ancora. Altre informazioni su queste strutture di dati sono disponibili nella documentazione della libreria di associazioni SQL di Azure.

Abilitare il ridimensionamento basato sul runtime

Facoltativamente, le funzioni possono essere ridimensionate automaticamente in base al numero di modifiche in sospeso da elaborare nella tabella utente. Per consentire alle funzioni di ridimensionare correttamente il piano Premium quando si usano i trigger SQL, è necessario abilitare il monitoraggio della scalabilità di runtime.

Nella portale di Azure, nell'app per le funzioni scegliere Configurazione e nella scheda Impostazioni runtime funzione impostare Monitoraggio della scalabilità di runtime su .

Screenshot del pannello portale di Azure per abilitare il ridimensionamento in fase di esecuzione.

Supporto di ripetizione dei tentativi

Altre informazioni sul supporto dei tentativi di trigger SQL e sulle tabelle di lease sono disponibili nel repository GitHub.

Tentativi di avvio

Se si verifica un'eccezione durante l'avvio, il runtime dell'host tenta automaticamente di riavviare il listener del trigger con una strategia di backoff esponenziale. Questi tentativi continuano fino a quando il listener non viene avviato correttamente o l'avvio viene annullato.

Tentativi di connessione interrotti

Se la funzione viene avviata correttamente, ma un errore causa l'interruzione della connessione , ad esempio il server offline, la funzione continua a provare e riaprire la connessione fino a quando la funzione non viene arrestata o la connessione ha esito positivo. Se la connessione viene ristabilita, l'elaborazione delle modifiche è stata interrotta.

Si noti che questi tentativi non rientrano nella logica di ripetizione dei tentativi di connessione inattiva predefinita che SqlClient può essere configurato con le ConnectRetryCount opzioni e ConnectRetryIntervalstringa di connessione. I tentativi di connessione inattiva predefiniti vengono tentati per primi e se questi non riescono a riconnettersi, l'associazione trigger tenta di ristabilire la connessione stessa.

Tentativi di eccezione della funzione

Se si verifica un'eccezione nella funzione utente durante l'elaborazione delle modifiche, il batch di righe attualmente in fase di elaborazione viene ritentato in 60 secondi. Durante questo periodo di tempo vengono elaborate altre modifiche, ma le righe del batch che hanno causato l'eccezione vengono ignorate fino a quando non è trascorso il periodo di timeout.

Se l'esecuzione della funzione ha esito negativo cinque volte in una riga per una determinata riga, tale riga viene completamente ignorata per tutte le modifiche future. Poiché le righe di un batch non sono deterministiche, le righe di un batch non riuscito potrebbero terminare in batch diversi nelle chiamate successive. Ciò significa che non tutte le righe nel batch non riuscito verranno necessariamente ignorate. Se altre righe nel batch causavano l'eccezione, le righe "valide" potrebbero terminare in un batch diverso che non ha esito negativo nelle chiamate future.

Passaggi successivi