如何使用 SqlRetryLogicBaseProvider 在 Azure SQL 纵向扩展/缩减期间重试连接How to use SqlRetryLogicBaseProvider to retry connections during Azure SQL Scaling Up/Down

How to use SqlRetryLogicBaseProvider to retry connections during azure sql scaling up/down

提问人:duroforce 提问时间:10/19/2023 最后编辑:duroforce 更新时间:10/20/2023 访问量:97

问:

我有一个 azure sql 数据库,它具有根据 dtu 使用情况进行纵向扩展/缩减的自动计划。在放大/缩小过程中,所有连接都会被丢弃。因此,我需要在我的应用程序中应用重试逻辑,因此当数据库完成扩展/缩减时,应用程序将尝试再次执行。

我使用的是 C# .NET 框架 4.7,其中 Microsoft.Data.SqlClient 库具有要配置的 SqlRetryLogicBaseProvider。

配置提供程序并调用“ExecuteReader”后,我扩展了数据库,连接丢失了,但重试逻辑从未触发,查询只是返回错误

无法继续执行,因为会话处于终止状态。
当前命令发生严重错误。
如果有结果,应丢弃。

此错误号已添加到我的错误列表中。

这是我的代码:

internal class Program
    {
        
        private const string CnnStringFormat = "Data Source = localhost; Initial Catalog = dbtest; User ID = sa; Password=aaaaaa;Encrypt=True;TrustServerCertificate=True";
        private static SqlConnection s_generalConnection = new SqlConnection(CnnStringFormat);
        static void Main(string[] args)
        {
            SqlCommand comando = new SqlCommand("spGetLoadTest") { CommandType = System.Data.CommandType.StoredProcedure };
            
            var options = new SqlRetryLogicOption()
            {
                NumberOfTries = 5,
                MaxTimeInterval = TimeSpan.FromSeconds(60),
                DeltaTime = TimeSpan.FromSeconds(15),
                TransientErrors = new List<int> { -1, -2, 0, 109, 233, 997, 1222, 10060, -2146232060, 596 }
        };

            var provider = SqlConfigurableRetryFactory.CreateExponentialRetryProvider(options);
            
            provider.Retrying += (object s, SqlRetryingEventArgs e) =>
            {
                NotificaRetry(e);
                var cmd = s as SqlCommand;
                cmd.Connection.Close();
                cmd.Connection.Open();
                cmd.CommandTimeout = 3000;
            };

            s_generalConnection.RetryLogicProvider = provider;
            s_generalConnection.Open();

            comando.Connection = s_generalConnection;
            comando.RetryLogicProvider = provider;

            SqlDataReader leitor = null;
            try
            {
                comando.CommandTimeout = 300;
                leitor = comando.ExecuteReader();
                var count = leitor.Depth;
                var colunas = leitor.FieldCount;
            }
            catch (Exception ex)
            {
                Console.WriteLine("ERROR: " + ex.Message);
            }
        }

        private static void NotificaRetry(SqlRetryingEventArgs e)
        {
            int attempts = e.RetryCount + 1;
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine($"attempt {attempts} - current delay time:{e.Delay} \n");
            Console.WriteLine($"error: {e.Exceptions[e.RetryCount-1].Message} \n");
            Console.ForegroundColor = ConsoleColor.DarkGray;
        }
    }

在扩大规模时,我超越了这一点,因为“Comando.ExecuteReader()“正在执行,应用程序将重试,并且不会返回错误。

编辑经过大量测试后,我意识到,当我收到错误编号为 0 时,重试逻辑永远不会被触发,即使它在错误列表中也是如此。有时我收到错误 109,并且错误 109 会触发重试逻辑。这让我感到困惑,是否存在某些类型的错误,即使列出重试,也永远不会尝试?

C# .NET Azure-sql-database retry-logic 复原

评论

0赞 akseli 10/19/2023
这回答了你的问题吗?处理数据库连接问题的正确方法
0赞 duroforce 10/19/2023
在阅读了所有答案和链接后,我仍然无法使其正常工作。我已经使用 Microsoft.Data.SqlClient RetryLogicProvider 实现了重试逻辑,如果它尝试连接并且数据库处于脱机状态,则该逻辑工作正常,但是当数据库在连接期间脱机时。ExecuteReader() 调用,命令返回错误并且重试逻辑永远不会被触发,我需要在这种情况下触发它,以便应用程序可以再次运行。
0赞 akseli 10/20/2023
这似乎描述了您的问题:github.com/dotnet/SqlClient/issues/1454
0赞 duroforce 10/20/2023
我没有指定 CommandBehavior.CloseConnection,我使用没有参数的 ExecuteReader(),不使用 CommandBehavior.CloseConnection。我编辑了我的帖子,描述了一些测试后的结果。当错误号为 0 时,永远不会触发重试逻辑,即使它位于 SqlRetryLogicConfiguration 的错误列表中 0。当出现错误编号 109 时,将触发重试逻辑。是否不可能使用错误编号 0 重试?毫无疑问,这是我在扩展/缩减 azure sql 数据库时收到的错误

答: 暂无答案