Aracılığıyla paylaş


Azure İşlevleri için MySQL için Azure Veritabanı tetikleyici bağlaması

MySQL için Azure Veritabanı tetikleyici bağlamaları, kullanıcı tablosunu değişiklikler (ekler ve güncelleştirmeler) için izler ve güncelleştirilmiş satır verileriyle işlevi çağırır.

MySQL için Azure Veritabanı tetikleyici bağlamaları, kullanıcı tablosunu değişiklikler için izlemek için ve sütun verilerini kullanır az_func_updated_at . Bu nedenle, tetikleyici desteğini kullanmadan önce MySQL tablosunda değişiklik izlemeye izin vermek için tablo yapısını değiştirmeniz gerekir. Aşağıdaki sorgu aracılığıyla bir tabloda değişiklik izlemeyi etkinleştirebilirsiniz. Örneğin, tabloda etkinleştirin Products :

ALTER TABLE Products
ADD az_func_updated_at TIMESTAMP DEFAULT 
CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;

Kiralamalar tablosu, kullanıcı tablosundaki birincil anahtara karşılık gelen tüm sütunları ve üç sütun daha içerir: az_func_AttemptCount, az_func_LeaseExpirationTimeve az_func_SyncCompletedTime. Birincil anahtar sütunlarından herhangi biri aynı ada sahipse, sonuç çakışmaları listeleyen bir hata iletisidir. Bu durumda tetikleyicinin çalışması için listelenen birincil anahtar sütunları yeniden adlandırılmalıdır.

İşlevselliğe genel bakış

Tetikleyici işlevi başlatıldığında iki ayrı döngü başlatır: değişiklik yoklama döngüsü ve kira yenileme döngüsü. İşlev durdurulana kadar bu döngüler sürekli çalışır.

MySQL için Azure Veritabanı tetikleyici bağlaması, değişiklikleri denetlemek için yoklama döngüsünü kullanır. Yoklama döngüsü, değişiklikleri algıladığında kullanıcı işlevini tetikler. Yüksek düzeyde döngü şu örneğe benzer:

while (true) {
    1. Get list of changes on table - up to a maximum number controlled by the MySql_Trigger_MaxBatchSize setting
    2. Trigger function with list of changes
    3. Wait for delay controlled by MySql_Trigger_PollingIntervalMs setting
}

Değişiklikler, yapıldıkları sırayla işlenir. En eski değişiklikler önce işlenir. Değişiklik işleme ile ilgili şu noktaları göz önünde bulundurun:

  • Değişiklikler aynı anda birden çok satırda gerçekleşirse, bunların işleve gönderilme sırası sütunun ve birincil anahtar sütunlarının az_func_updated_at artan sırasına bağlıdır.
  • Değişiklikler bir satır için toplu olarak oluşturulur. Döngünün her yinelemesi arasında bir satırda birden çok değişiklik olursa, yalnızca bu satır için var olan en son değişiklik girişi dikkate alınır.

Not

Şu anda Yönetilen kimlikler, Azure İşlevleri ile MySQL için Azure Veritabanı arasındaki bağlantılarda desteklenmemektedir.

Örnek kullanım

MySQL için Azure Veritabanı tetikleyicisi için daha fazla örnek GitHub deposunda bulunabilir.

Örnek bir Product sınıfa ve buna karşılık gelen bir veritabanı tablosuna başvurur:

namespace AzureMySqlSamples.Common
{
    public class Product
    {
        public int? ProductId { get; set; }

        public string Name { get; set; }

        public int Cost { get; set; }

        public override bool Equals(object obj)
        {
            if (obj is Product)
            {
                var that = obj as Product;
                return this.ProductId == that.ProductId && this.Name == that.Name && this.Cost == that.Cost;
            }
            return false;
        }
    }
DROP TABLE IF EXISTS Products;

CREATE TABLE Products (
  ProductId int PRIMARY KEY,
  Name varchar(100) NULL,
  Cost int NULL
);

Tabloya bir sütun ekleyerek veritabanında değişiklik izlemeyi etkinleştirirsiniz:

ALTER TABLE <table name>  
ADD COLUMN az_func_updated_at TIMESTAMP 
DEFAULT CURRENT_TIMESTAMP 
ON UPDATE CURRENT_TIMESTAMP;

MySQL için Azure Veritabanı tetikleyicisi, nesneleri listeleyen IReadOnlyList<MySqlChange<T>> öğesine MySqlChangebağlanır. Her nesnenin iki özelliği vardır:

  • Item: Değiştirilen öğe. Öğenin türü, sınıfında görüldüğü gibi tablo şemasını ToDoItem izlemelidir.
  • Operation: Numaralandırmadan bir MySqlChangeOperation değer. Olası değer Update hem eklemeler hem de güncelleştirmeler içindir.

Aşağıdaki örnekte, tabloda değişiklikler olduğunda çağrılan bir C# işlevi gösterilmektedir Product :

using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.Functions.Worker.Extensions.MySql;
using Microsoft.Extensions.Logging;
using AzureMySqlSamples.Common;

namespace AzureMySqlSamples.TriggerBindingSamples
{
        private static readonly Action<ILogger, string, Exception> _loggerMessage = LoggerMessage.Define<string>(LogLevel.Information, eventId: new EventId(0, "INFO"), formatString: "{Message}");

        [Function(nameof(ProductsTrigger))]
        public static void Run(
            [MySqlTrigger("Products", "MySqlConnectionString")]
            IReadOnlyList<MySqlChange<Product>> changes, FunctionContext context)
        {
            ILogger logger = context.GetLogger("ProductsTrigger");
            // The output is used to inspect the trigger binding parameter in test methods.
            foreach (MySqlChange<Product> change in changes)
            {
                Product product = change.Item;
                _loggerMessage(logger, $"Change operation: {change.Operation}", null);
                _loggerMessage(logger, $"Product Id: {product.ProductId}, Name: {product.Name}, Cost: {product.Cost}", null);
            }
        }
}

Örnek kullanım

MySQL için Azure Veritabanı tetikleyicisi için daha fazla örnek GitHub deposunda bulunabilir.

Örnek bir Product sınıfa, sınıfa MySqlChangeProduct , MySqlChangeOperation numaralandırmaya ve buna karşılık gelen bir veritabanı tablosuna başvurur.

Product.java adlı ayrı bir dosyada:

package com.function.Common;

import com.fasterxml.jackson.annotation.JsonProperty;

public class Product {
    @JsonProperty("ProductId")
    private int ProductId;
    @JsonProperty("Name")
    private String Name;
    @JsonProperty("Cost")
    private int Cost;

    public Product() {
    }

    public Product(int productId, String name, int cost) {
        ProductId = productId;
        Name = name;
        Cost = cost;
    }
}

MySqlChangeProduct.java adlı ayrı bir dosyada:

package com.function.Common;

public class MySqlChangeProduct {
    private MySqlChangeOperation Operation;
    private Product Item;

    public MySqlChangeProduct() {
    }

    public MySqlChangeProduct(MySqlChangeOperation operation, Product item) {
        this.Operation = operation;
        this.Item = item;
    }
}

MySqlChangeOperation.java adlı ayrı bir dosyada:

package com.function.Common;

import com.google.gson.annotations.SerializedName;

public enum MySqlChangeOperation {
    @SerializedName("0")
    Update
}
DROP TABLE IF EXISTS Products;

CREATE TABLE Products (
  ProductId int PRIMARY KEY,
  Name varchar(100) NULL,
  Cost int NULL
);

Tabloya aşağıdaki sütunu ekleyerek veritabanında değişiklik izlemeyi etkinleştirirsiniz:

ALTER TABLE <table name>  
ADD COLUMN az_func_updated_at TIMESTAMP 
DEFAULT CURRENT_TIMESTAMP 
ON UPDATE CURRENT_TIMESTAMP;

MySQL için Azure Veritabanı tetikleyicisi, bir nesne dizisi MySqlChangeProduct[] olan öğesine MySqlChangeProductbağlanır. Her nesnenin iki özelliği vardır:

  • item: Değiştirilen öğe. Öğenin türü, sınıfında görüldüğü gibi tablo şemasını Product izlemelidir.
  • operation: Numaralandırmadan bir MySqlChangeOperation değer. Olası değer Update hem eklemeler hem de güncelleştirmeler içindir.

Aşağıdaki örnekte, tabloda değişiklikler olduğunda çağrılan bir Java işlevi gösterilmektedir Product :

/**
 * Copyright (c) Microsoft Corporation. All rights reserved.
 * Licensed under the MIT License. See License.txt in the project root for
 * license information.
 */

package com.function;

import com.microsoft.azure.functions.ExecutionContext;
import com.microsoft.azure.functions.annotation.FunctionName;
import com.microsoft.azure.functions.mysql.annotation.MySqlTrigger;
import com.function.Common.MySqlChangeProduct;
import com.google.gson.Gson;

import java.util.logging.Level;

public class ProductsTrigger {
    @FunctionName("ProductsTrigger")
    public void run(
            @MySqlTrigger(
                name = "changes",
                tableName = "Products",
                connectionStringSetting = "MySqlConnectionString")
                MySqlChangeProduct[] changes,
            ExecutionContext context) {

        context.getLogger().log(Level.INFO, "MySql Changes: " + new Gson().toJson(changes));
    }
}

Örnek kullanım

MySQL için Azure Veritabanı tetikleyicisi için daha fazla örnek GitHub deposunda bulunabilir.

Örnek bir Product veritabanı tablosuna başvurur:

DROP TABLE IF EXISTS Products;

CREATE TABLE Products (
  ProductId int PRIMARY KEY,
  Name varchar(100) NULL,
  Cost int NULL
);

Tabloya bir sütun ekleyerek veritabanında değişiklik izlemeyi etkinleştirirsiniz:

ALTER TABLE <table name>  
ADD COLUMN az_func_updated_at TIMESTAMP 
DEFAULT CURRENT_TIMESTAMP 
ON UPDATE CURRENT_TIMESTAMP;

MySQL için Azure Veritabanı tetikleyicisi, nesneleri listeleyen öğesine Productbağlanır. Her nesnenin iki özelliği vardır:

  • item: Değiştirilen öğe. Öğenin yapısı tablo şemasını izler.
  • operation: Olası değer Update hem eklemeler hem de güncelleştirmeler içindir.

Aşağıdaki örnekte, tabloda değişiklikler olduğunda çağrılan bir PowerShell işlevi gösterilmektedir Product .

Aşağıdaki örnek, function.json dosyasındaki verileri bağlamadır:

{
    "bindings": [
      {
        "name": "changes",
        "type": "mysqlTrigger",
        "direction": "in",
        "tableName": "Products",
        "connectionStringSetting": "MySqlConnectionString"
      }
    ],
    "disabled": false
  }

Yapılandırma bölümünde bu özellikler açıklanır.

Aşağıdaki örnek, run.ps1 dosyasındaki işlev için örnek PowerShell kodudur:

using namespace System.Net

param($changes)
# 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 = $changes | ConvertTo-Json -Compress
Write-Host "MySql Changes: $changesJson"

Örnek kullanım

MySQL için Azure Veritabanı tetikleyicisi için daha fazla örnek GitHub deposunda bulunabilir.

Örnek bir Product veritabanı tablosuna başvurur:

DROP TABLE IF EXISTS Products;

CREATE TABLE Products (
  ProductId int PRIMARY KEY,
  Name varchar(100) NULL,
  Cost int NULL
);

Tabloya bir sütun ekleyerek veritabanında değişiklik izlemeyi etkinleştirirsiniz:

ALTER TABLE <table name>  
ADD COLUMN az_func_updated_at TIMESTAMP 
DEFAULT CURRENT_TIMESTAMP 
ON UPDATE CURRENT_TIMESTAMP;

MySQL için Azure Veritabanı tetikleyicisi, bir nesne dizisi olan öğesine Changesbağlanır. Her nesnenin iki özelliği vardır:

  • item: Değiştirilen öğe. Öğenin yapısı tablo şemasını izler.
  • operation: Olası değer Update hem eklemeler hem de güncelleştirmeler içindir.

Aşağıdaki örnekte, tabloda değişiklikler olduğunda çağrılan bir JavaScript işlevi gösterilmektedir Product .

Aşağıdaki örnek, function.json dosyasındaki verileri bağlamadır:

{
    "bindings": [
      {
        "name": "changes",
        "type": "mysqlTrigger",
        "direction": "in",
        "tableName": "Products",
        "connectionStringSetting": "MySqlConnectionString",
      }
    ],
    "disabled": false
  }

Yapılandırma bölümünde bu özellikler açıklanır.

Aşağıdaki örnek, dosyasındaki index.js işlev için örnek JavaScript kodudur:

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

Örnek kullanım

MySQL için Azure Veritabanı tetikleyicisi için daha fazla örnek GitHub deposunda bulunabilir.

Örnek bir Product veritabanı tablosuna başvurur:

DROP TABLE IF EXISTS Products;

CREATE TABLE Products (
  ProductId int PRIMARY KEY,
  Name varchar(100) NULL,
  Cost int NULL
);

Tabloya bir sütun ekleyerek veritabanında değişiklik izlemeyi etkinleştirirsiniz:

ALTER TABLE <table name>  
ADD COLUMN az_func_updated_at TIMESTAMP 
DEFAULT CURRENT_TIMESTAMP 
ON UPDATE CURRENT_TIMESTAMP;

Not

Python için Azure İşlevleri sürüm 1.22.0b4 kullanmanız gerekir.

MySQL için Azure Veritabanı tetikleyicisi, nesneleri listeleyen adlı Productbir değişkene bağlanır. Her nesnenin iki özelliği vardır:

  • item: Değiştirilen öğe. Öğenin yapısı tablo şemasını izler.
  • operation: Olası değer Update hem eklemeler hem de güncelleştirmeler içindir.

Aşağıdaki örnekte, tabloda değişiklikler olduğunda çağrılan bir Python işlevi gösterilmektedir Product .

Aşağıdaki örnek, function_app.py dosyası için örnek Python kodudur:

import json
import logging
import azure.functions as func

app = func.FunctionApp()

# The function is triggered when a change (insert, update)
# is made to the Products table.
@app.function_name(name="ProductsTrigger")
@app.mysql_trigger(arg_name="products",
table_name="Products",
connection_string_setting="MySqlConnectionString")

def products_trigger(products: str) -> None:
logging.info("MySQL Changes: %s", json.loads(products))

Özellikler

Öznitelik özelliği Açıklama
TableName Gerekli. Tetikleyicinin izlediği tablonun adı.
ConnectionStringSetting Gerekli. Değişiklikler için izlenen tabloyu içeren veritabanının bağlantı dizesini içeren bir uygulama ayarının adı. Bağlantı dizesi ayarının adı, MySQL için Azure Veritabanı bağlantı dizesini içeren uygulama ayarına (yerel geliştirme için local.settings.json) karşılık gelir.
LeasesTableName isteğe bağlı. Kiraları depolamak için tablonun adı. Belirtilmezse, adı olur Leases_{FunctionId}_{TableId}.

Ek Açıklamalar

Java işlevleri çalışma zamanı kitaplığında, değerleri MySQL için Azure Veritabanı'ndan gelen parametrelerde ek açıklamayı kullanın@MySQLTrigger. Bu ek açıklama aşağıdaki öğeleri destekler:

Öğe Açıklama
name Gerekli. Tetikleyicinin bağlandığını parametrenin adı.
tableName Gerekli. Tetikleyicinin izlediği tablonun adı.
connectionStringSetting Gerekli. Değişiklikler için izlenen tabloyu içeren veritabanının bağlantı dizesini içeren bir uygulama ayarının adı. Bağlantı dizesi ayarının adı, MySQL için Azure Veritabanı bağlantı dizesini içeren uygulama ayarına (yerel geliştirme için local.settings.json) karşılık gelir.
LeasesTableName isteğe bağlı. Kiraları depolamak için tablonun adı. Belirtilmezse, adı olur Leases_{FunctionId}_{TableId}.

Yapılandırma

Aşağıdaki tabloda, function.json dosyasında ayarladığınız bağlama yapılandırma özellikleri açıklanmaktadır:

Mülkiyet Açıklama
name Gerekli. Tetikleyicinin bağlandığını parametrenin adı.
type Gerekli. olarak ayarlanmalıdır MysqlTrigger.
direction Gerekli. olarak ayarlanmalıdır in.
tableName Gerekli. Tetikleyicinin izlediği tablonun adı.
connectionStringSetting Gerekli. Değişiklikler için izlenen tabloyu içeren veritabanının bağlantı dizesini içeren bir uygulama ayarının adı. Bağlantı dizesi ayarının adı, MySQL için Azure Veritabanı bağlantı dizesini içeren uygulama ayarına (yerel geliştirme için local.settings.json) karşılık gelir.
LeasesTableName isteğe bağlı. Kiraları depolamak için tablonun adı. Belirtilmezse, adı olur Leases_{FunctionId}_{TableId}.

İsteğe bağlı yapılandırma

Yerel geliştirme veya bulut dağıtımları için MySQL için Azure Veritabanı tetikleyicisi için aşağıdaki isteğe bağlı ayarları yapılandırabilirsiniz.

host.json

Bu bölümde, 2.x ve sonraki sürümlerde bu bağlama için kullanılabilen yapılandırma ayarları açıklanmaktadır. host.json dosyasındaki ayarlar, bir işlev uygulaması örneğindeki tüm işlevler için geçerlidir. İşlev uygulaması yapılandırma ayarları hakkında daha fazla bilgi için bkz. Azure İşlevleri içinhost.json başvuru.

Ayar Varsayılan Açıklama
MaxBatchSize 100 Tetiklenen işleve gönderilmeden önce tetikleyici döngüsünün her yinelemesiyle işlenen en fazla değişiklik sayısı.
PollingIntervalMs 1000 Her bir değişiklik toplu işleminin işlenmesi arasındaki milisaniye cinsinden gecikme. (1.000 ms 1 saniyedir.)
MaxChangesPerWorker 1000 Uygulama çalışanı başına izin verilen kullanıcı tablosundaki bekleyen değişikliklerin sayısıyla ilgili üst sınır. Değişiklik sayısı bu sınırı aşarsa ölçeği genişletmeye neden olabilir. Bu ayar yalnızca çalışma zamanı temelli ölçeklendirmenin etkinleştirildiği Azure işlev uygulamaları için geçerlidir.

Örnek host.json dosyası

İsteğe bağlı ayarları içeren bir örnek host.json dosyası aşağıda verilmişti:

{
  "version": "2.0",
  "extensions": {
      "MySql": {
        "MaxBatchSize": 300,
        "PollingIntervalMs": 1000,
        "MaxChangesPerWorker": 100
      }
  },
  "logging": {
    "applicationInsights": {
      "samplingSettings": {
        "isEnabled": true,
        "excludedTypes": "Request"
      }
    },
    "logLevel": {
      "default": "Trace"
    }
  }
}

local.setting.json

local.settings.json dosyası, yerel geliştirme araçlarının kullandığı uygulama ayarlarını ve ayarlarını depolar. local.settings.json dosyasındaki ayarlar yalnızca projenizi yerel olarak çalıştırdığınızda kullanılır. Projenizi Azure'da yayımladığınızda, işlev uygulamasının uygulama ayarlarına gerekli ayarları da eklediğinizden emin olun.

Önemli

local.settings.json dosyası bağlantı dizeleri gibi gizli diziler içerebileceğinden, dosyayı hiçbir zaman uzak bir depoda depolamamalısınız. Azure İşlevleri'ni destekleyen araçlar, projenizin dağıtıldığı işlev uygulamasındaki uygulama ayarlarıyla local.settings.json dosyasındaki ayarları eşitlemenin yollarını sağlar.

Ayar Varsayılan Açıklama
MySql_Trigger_BatchSize 100 Tetiklenen işleve gönderilmeden önce tetikleyici döngüsünün her yinelemesiyle işlenen en fazla değişiklik sayısı.
MySql_Trigger_PollingIntervalMs 1000 Her bir değişiklik toplu işleminin işlenmesi arasındaki milisaniye cinsinden gecikme. (1.000 ms 1 saniyedir.)
MySql_Trigger_MaxChangesPerWorker 1000 Uygulama çalışanı başına izin verilen kullanıcı tablosundaki bekleyen değişikliklerin sayısıyla ilgili üst sınır. Değişiklik sayısı bu sınırı aşarsa ölçeği genişletmeye neden olabilir. Bu ayar yalnızca çalışma zamanı temelli ölçeklendirmenin etkinleştirildiği Azure işlev uygulamaları için geçerlidir.

Örnek local.settings.json dosyası

İsteğe bağlı ayarları içeren örnek bir local.settings.json dosyası aşağıda verilmişti:

{
  "IsEncrypted": false,
  "Values": {
    "AzureWebJobsStorage": "UseDevelopmentStorage=true",
    "FUNCTIONS_WORKER_RUNTIME": "dotnet",
    "MySqlConnectionString": "",
    "MySql_Trigger_MaxBatchSize": 300,
    "MySql_Trigger_PollingIntervalMs": 1000,
    "MySql_Trigger_MaxChangesPerWorker": 100
  }
}

Değişiklik izlemeyi ayarlama (gerekli)

MySQL için Azure Veritabanı tetikleyicisi ile kullanılacak değişiklik izlemeyi ayarlamak için bir işlev kullanarak tabloya sütun eklemeniz gerekir. Visual Studio Code veya Azure Data Studio dahil olmak üzere sorguları çalıştırmayı destekleyen herhangi bir MySQL aracından bu adımları tamamlayabilirsiniz.

MySQL için Azure Veritabanı tetikleyici bağlamaları, kullanıcı tablosunu değişiklikler için izlemek için ve sütun verilerini kullanır az_func_updated_at . Bu nedenle, tetikleyici desteğini kullanmadan önce MySQL tablosunda değişiklik izlemeye izin vermek için tablo yapısını değiştirmeniz gerekir. Aşağıdaki sorgu aracılığıyla bir tabloda değişiklik izlemeyi etkinleştirebilirsiniz. Örneğin, tabloda etkinleştirin Products :

ALTER TABLE Products;
ADD az_func_updated_at 
TIMESTAMP DEFAULT CURRENT_TIMESTAMP 
ON UPDATE CURRENT_TIMESTAMP;

Kiralamalar tablosu, kullanıcı tablosundaki birincil anahtara karşılık gelen tüm sütunları ve iki sütun daha içerir: az_func_AttemptCount ve az_func_LeaseExpirationTime. Birincil anahtar sütunlarından herhangi biri aynı ada sahipse, sonuç çakışmaları listeleyen bir hata iletisidir. Bu durumda tetikleyicinin çalışması için listelenen birincil anahtar sütunları yeniden adlandırılmalıdır.

Çalışma zamanı temelli ölçeklendirmeyi etkinleştirme

İsteğe bağlı olarak, işlevleriniz kullanıcı tablosunda işlenmeyi bekleyen değişikliklerin sayısına göre otomatik olarak ölçeklendirilebilir. MySQL için Azure Veritabanı tetikleyicilerini kullanırken işlevlerinizin Premium planında düzgün ölçeklendirilmesine izin vermek için çalışma zamanı ölçeği izlemeyi etkinleştirmeniz gerekir.

  1. Azure portalında işlev uygulamanızda Yapılandırma'yı seçin.

  2. İşlev çalışma zamanı ayarları sekmesinde, Çalışma Zamanı Ölçeği İzleme için Açık'ı seçin.

    Çalışma zamanı ölçeklendirmesini etkinleştirmeye yönelik Azure portal alanının ekran görüntüsü.

Desteği yeniden deneyin

Başlangıç yeniden denemeleri

Başlatma sırasında bir özel durum oluşursa, konak çalışma zamanı tetikleyici dinleyicisini üstel geri alma stratejisiyle otomatik olarak yeniden başlatmayı dener. Bu yeniden denemeler, dinleyici başarıyla başlatılana veya başlatma iptal edilene kadar devam eder.

İşlev özel durumu yeniden denemeleri

Değişiklik işleme sırasında kullanıcı işlevinde bir özel durum oluşursa, şu anda işlenmekte olan satır toplu işlemi 60 saniye içinde yeniden denenir. Bu süre boyunca diğer değişiklikler normal şekilde işlenir, ancak özel duruma neden olan toplu işteki satırlar zaman aşımı süresi geçene kadar yoksayılır.

İşlev yürütmesi belirli bir satır için ardışık beş kez başarısız olursa, bu satır gelecekteki tüm değişiklikler için yoksayılır. Toplu işteki satırlar belirlenimci olmadığından, başarısız toplu işteki satırlar sonraki çağrılarda farklı toplu işlerle sonuçlanabilir. Bu davranış, başarısız toplu işteki tüm satırların mutlaka yoksayılmaması anlamına gelir. Toplu işteki diğer satırlar özel duruma neden olursa, "iyi" satırlar gelecekteki çağrılarda başarısız olmayan farklı bir toplu işte sonuçlanabilir.