连续连接数据库时出错

use*_*324 37 c# sql azure azure-sql-database

当我在连续循环中从数据库查询时,一段时间后我收到一个错误:

引发的异常可能是由于瞬态故障引起的.如果要连接到SQL Azure数据库,请考虑使用SqlAzureExecutionStrategy.

通常它工作正常.

小智 15

连接到SQL数据库时,必须考虑瞬时连接故障.例如,当推出更新,硬件失败等时,可能会发生这些连接失败.您看到的错误表明发生了这些事情之一,这是您断开连接的方式.按照Anbuj的建议启用执行策略应该可以解决问题.


She*_*har 13

如果您使用EF Core配置重试失败以进行弹性连接:

protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
    optionsBuilder.UseSqlServer("your_connection_string", builder =>
        {
            builder.EnableRetryOnFailure(5, TimeSpan.FromSeconds(10), null);
        });
    base.OnConfiguring(optionsBuilder);
}
Run Code Online (Sandbox Code Playgroud)


Sha*_*anu 9

启用此处提到的执行策略:https://msdn.microsoft.com/en-us/data/dn456835.aspx.在设计Azure SQL DB时,必须设计瞬态连接故障,因为后端更新,硬件故障,负载平衡有时会导致间歇性故障.


oma*_*lat 7

我可以看到没有人将解决方案放在实体框架而不是 EF core 的情况下。实现 SqlAzureExecutionStrategy 最简单的方法是:

  1. 转到包含以下内容的 Context.cs 文件:public partial class YourEntity : DbContext

  2. 添加参考:using System.Data.Entity.SqlServer;

  3. 在文件末尾添加另一个包含以下代码的类:

    public MyConfiguration()
    {
        SetExecutionStrategy("System.Data.SqlClient", () => new SqlAzureExecutionStrategy());
        SetDefaultConnectionFactory(new LocalDbConnectionFactory("mssqllocaldb"));
    }
    
    Run Code Online (Sandbox Code Playgroud)

您可以参考此文档以获取更多信息。

  • 我正在使用 SQL Server。我应该使用 SqlAzureExecutionStrategy 吗? (7认同)

小智 6

我想为那些像我一样遇到此错误的人做出贡献,即使他们没有处于必须与 Azure 或云中其他平台上的数据库进行交互的情况。

第一个目标是找到问题的确切根源;像我一样,许多人都会与异常文本和一英里长的堆栈跟踪字符串发生冲突。对我来说,处理 InnerExceptions 的 matryoshka 以获得数据库提供程序在关闭连接之前发出的真实消息(该消息在消息发生时处于活动状态!)非常有用。或者,如果可能的话,从外部工具监控数据库事务就足够了,该工具允许您检查与正在进行的 TSQL 操作相关的任何错误(例如 SQL Server Profiler)。

在我的例子中,场景是这样的:同一个程序(它是一个 Windows 服务)的 2 个实例在表中插入记录。两个特点:

  • 对于 Windows 服务,例如 Form 或 WPF 桌面应用程序,DbContext 的生命周期通常较长,并且可以将其链接到正在处理的 Form,而不是在项目的整个持续时间内保持活动状态定期刷新以清除截至该时刻的缓存值;
  • 目标表有自己的自动增量(整数)键字段

在这种情况下,所有服务的实例同时尝试写入同一个表,并且使用 EF6 执行的每个写入操作都会生成一个查询,其中包含一个非常特定的选择,用于检索和增强它代表身份的关键字段。像这样的东西:

INSERT [dbo].[People]([Name]) VALUES (@0)
SELECT [Id], [SomeId]
FROM [dbo].[People]
WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()
Run Code Online (Sandbox Code Playgroud)

我的代码是:

People entry = new People();
entry.name = "ABCD";
_ctx.Set<People>().Add(entry);
await _ctx.SaveChangesAsync();
Run Code Online (Sandbox Code Playgroud)

这种写法会导致两个进程之间出现并发的情况(特别是当表有大约5M条记录时),这会导致SQL引擎解析一个请求并取消另一个请求。调用程序的解释正是“发生了异常,可能是由于暂时性故障。如果您要连接到 SQL Azure 数据库,请考虑使用 SqlAzureExecutionStrategy。

为了解决这个问题,我不得不放弃恢复分配给新记录的增量 id,将表视为堆栈,并使用以下方法将写入操作减少为直接插入操作:

await _ctx.Database.ExecuteSqlCommandAsync("INSERT INTO ....");
Run Code Online (Sandbox Code Playgroud)

或者,可以使用两个不涉及 EF TSQL 解析器的写入操作来优化操作,并且还可以检索分配给最后添加的记录的标识符。


Tri*_*hak 5

我发布这个答案是因为我在研究问题答案时遇到很多问题。以下是我收到的详细错误消息:

由于错误太长,将错误分为几个部分:

  1. System.Data.Entity.Core.EntityException:*已引发异常,可能是由于暂时性故障所致。如果要连接到 SQL Azure 数据库,请考虑使用 SqlAzureExecutionStrategy。* --->

  2. System.Data.Entity.Core.EntityCommandExecutionException:执行命令定义时发生错误。有关详细信息,请参阅内部异常。---> System.Data.SqlClient.SqlException:资源 ID: 1。数据库的请求限制为 30,已达到。请参阅“ http://go.microsoft.com/fwlink/?LinkId=267637 ”以获取帮助。在System.Data.SqlClient.SqlConnection.OnError(SqlException异常,布尔breakConnection,Action`1wrappCloseInAction)

经过研究发现,这与Azure SQL数据库最大登录数限制有关。我使用的是“基本”服务轮胎,可以登录的最大并发用户数为 30。

Azure 的定价层在性能方面存在显着差异。为了实现这一目标,他们限制了许多性能指标,例如 CPU 功率、每分钟请求数等。

这意味着,如果您超出层级,您的请求将开始排队,因为 CPU 功率/请求量太高而无法处理。这会导致超时,然后随着请求等待处理,请求限制会增加。最终,它达到了数据库基本上崩溃的地步。

我的经验是,较低的数据库级别(例如 S0 和 S1)功能不足,不应该用于开发或非常基本的站点以外的任何用途。

Azure 门户中有一些很棒的工具可让您调试数据库的运行情况,例如 CPU 图表、索引顾问和查询性能洞察。

以下是相关链接:

结论:

谢谢。