4

我需要延迟 DB2 中数据插入的执行。由于以下数据库部署原因,我需要等待 10 分钟

注册过程

  • 第 1 步:我在 DB1 的表中创建了一个条目。
  • 第 2 步:开始创建 DB2 的过程 - 数据库创建 DB2
  • 第 3 步:10 分钟后需要在创建的 DB2 中进行条目。

如何使用 Azure 函数来实现?

4

3 回答 3

5

一种方法是将消息发送到ScheduledEnqueueTimeUtc属性设置为 10 分钟后的服务总线队列。(文档

然后有一个由该服务总线队列触发的 Azure 函数。(文档

于 2017-08-16T11:51:27.640 回答
1

因为以下数据库部署原因我需要等待 10 分钟:创建后无法立即打开 Azure SQL Server DB

作为全局配置选项host.json状态functionTimeout如下:

functionTimeout指示所有函数的超时持续时间的值。

  • 在动态 SKU 中,有效范围为 1 秒到 10 分钟,默认值为 5 分钟。
  • 在付费 SKU 中没有限制,默认值为 null(表示没有超时)。

据我了解,如果您的注册过程需要在 下进行CreateTenant,我假设您可以在 Step2 之后检查数据库的创建状态,然后当数据库在线时,您可以进行 Step3。我为这个场景写了一个示例,你可以参考它:

运行.csx

#r "System.Configuration"
#r "System.Data"

using System.Net;

using System.Configuration;
using System.Data.SqlClient;
using System.Threading.Tasks;

public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
    // Get request body
    dynamic data = await req.Content.ReadAsAsync<object>();
    string dataBase_Name = data?.dataBase_Name;
    string source_dataBase_Name = data?.source_dataBase_Name;

    log.Info("Begin create the database for the tenant...");

    //Create the database
    var str = ConfigurationManager.ConnectionStrings["sqldb_connection"].ConnectionString;
    using (SqlConnection conn = new SqlConnection(str))
    {
        conn.Open();
        var copyDbSql = $"CREATE DATABASE [{dataBase_Name}] as COPY OF [{source_dataBase_Name}] (SERVICE_OBJECTIVE='S0')";
        try
        {
            using (SqlCommand cmd = new SqlCommand(copyDbSql, conn))
            {   
                //30s by default, https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.commandtimeout.aspx
                //cmd.CommandTimeout=0; 
                cmd.ExecuteNonQuery(); //30s timeout if the server is not responding, you could change it, but I would leave it for default.
                log.Info("create database statement executed...");
            }
        }
        catch (Exception e)
        {
            //exception for timeout and so on
            //you need to make sure the database creation has been accepted, you could execute the following sql statement:
            //SELECT * FROM sys.dm_database_copies where partner_database=N'{your-database-name}'
            log.Info(e.Message);
        }
    }

    log.Info("check the creation processing...");
    //If the database creation is accepted, then check the creation status of your database
    bool status = false;
    using (SqlConnection conn = new SqlConnection(str))
    {
        conn.Open();
        var text = "Select count(*) from master.sys.databases where name=N'" + dataBase_Name + "' and state_desc='ONLINE'";
        using (SqlCommand cmd = new SqlCommand(text, conn))
        {
            do
            {
                var count = await cmd.ExecuteScalarAsync();
                if (count != null && Convert.ToInt32(count) > 0)
                    status = true;
                if (status)
                    log.Info($"Database [{dataBase_Name}] is online!!!");
                else
                {
                    log.Info($"Database [{dataBase_Name}] is creating...");
                    Task.Delay(TimeSpan.FromSeconds(30)).Wait(); //sleep for 30s
                }
            } while (!status);
        }
    }

    if (status)
    {
        //Database is online, do other operations
    }
    return req.CreateResponse(HttpStatusCode.OK, "");
}

结果:

在此处输入图像描述

此外,正如 Mikhail 建议的那样,您可以在执行数据库创建后发送队列消息,然后使用 QueueTrigger 获取消息并检查数据库的状态并在数据库联机后插入条目以解耦您的注册过程。

这里有一些有用的教程,你可以参考它们:

使用 Azure Functions 连接到 Azure SQL 数据库

sys.dm_database_copies(Azure SQL 数据库)

于 2017-08-17T08:59:46.550 回答
1

我认为现在在 Azure Function V2 和 Durable Functions 扩展之后有很多解决方案:

1-您可以使用持久函数(链接),这样您就可以编排整个工作流程,然后将所有要延迟的代码放在单独的函数中,然后使用普通的 Task.Delay 延迟它

2-您可以使用 Azure Logic Apps,您可以对其进行配置并安排它根据时间运行(链接)。

3-您也可以使用计划的服务总线队列(链接)。

4-您可以通过使用 SQL 作业在数据库端自行延迟来开箱即用地思考,但这取决于您的业务和架构。

于 2018-11-20T15:44:55.840 回答