连续连接数据库时出现错误

105

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

已引发异常,可能是由于瞬态故障导致的。如果您正在连接到 SQL Azure 数据库,请考虑使用 SqlAzureExecutionStrategy。

通常情况下它都能正常工作。


请检查您的服务器日志(SQL Server所在位置)。这可能是由于您的服务器拒绝了持续请求。使用ULS查看器来检查日志。如果是这种情况,您可能需要修改服务器设置。 - anbuj
是的。假设您可以访问您的Azure环境。 - anbuj
抱歉,我们无法访问Azure环境。 - user3928324
3
那么,唯一的方法是为Azure DB启用执行策略。请尝试访问此链接 https://msdn.microsoft.com/zh-cn/data/dn456835.aspx。 - anbuj
5
当我在本地计算机上使用代理或VPN连接到远程数据库时,在Visual Studio中遇到了这个错误。 - Mohsen Tavoosi محسن طاوسی
显示剩余5条评论
14个回答

76

如果您正在使用EF Core,则可以配置重试失败以实现弹性连接:

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

28

连接到 SQL 数据库时,您需要考虑短暂的连接故障。这些连接故障可能发生在更新发布、硬件故障等情况下。您看到的错误表明其中一件事情发生了,这就是为什么您的连接会断开的原因。按照 Anbuj 的建议启用执行策略应该可以解决问题。


1
这些连接失败可能会在更新推出、硬件故障等情况下发生。我认为还有更加平凡的原因。我在我们每晚的单元测试运行中都遇到了相同的错误,而且不仅是偶尔出现,而是在过去几个月的每次测试运行中都导致了500多个测试中的一些测试失败。 - O. R. Mapper
@O.R.Mapper,你解决了上述问题吗?我也遇到了同样的问题。 - Jagadisha B S
@JagadishaBS:不,说实话,我还没有机会与我们的数据库专家进行分析会话。 - O. R. Mapper
@O.R.Mapper 谢谢。 - Jagadisha B S
只是再添加另一个“平凡”的用例,就像上面所说的一样,针对我们在 Azure 上的开发服务器,我们有一个设置,如果数据库实例超过一小时未接收到任何活动,则关闭该实例(以节省未使用资源的成本),因此第一个请求往往会导致这种问题。 - Kieran Osgood

10

7

我注意到没有人提供Entity Framework而非EF core的解决方案。实现SqlAzureExecutionStrategy最简单的方法是:

  1. Go to Context.cs file that contains: public partial class YourEntity : DbContext

  2. add the reference: using System.Data.Entity.SqlServer;

  3. add another class at the end of the file containing the following code:

    public MyConfiguration()
    {
        SetExecutionStrategy("System.Data.SqlClient", () => new SqlAzureExecutionStrategy());
        SetDefaultConnectionFactory(new LocalDbConnectionFactory("mssqllocaldb"));
    }
    
您可以查阅此文档获取更多信息。

7
我正在使用SQL Server,是否应该使用SqlAzureExecutionStrategy? - Silny ToJa

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 exception, Boolean breakConnection, Action`1 wrapCloseInAction)处

经过调查,我发现这与Azure SQL数据库最大登录限制有关。我使用的是“基本”服务层,最大并发用户登录数为30。
Azure有定价层,性能差异很大。为了实现这一点,他们会限制很多性能指标,例如CPU功率、每分钟请求数等。
这意味着如果您超出了定价层,您的请求将开始排队,因为CPU功率/请求量太高而无法处理。这导致超时,然后请求限制增加,因为请求等待被处理。最终,它会达到数据库基本上崩溃的地步。
我的经验是较低的数据库级别,如S0和S1,性能不足,除了开发或非常基本的站点外,不应该用于其他任何用途。
Azure门户中有一些很棒的工具,可以让您调试数据库的情况,例如CPU图表、索引顾问和查询性能见解。
以下是相关链接:

结论:

谢谢。


第一部分的链接已经失效了。 - LP. Gonçalves

5

我希望能为那些和我一样遇到了这个错误但并非在Azure或云平台上与数据库进行交互的人做出贡献。

首要目标是确定问题的确切来源,像我一样的许多人都会遭遇异常文本和一长串堆栈跟踪字符串。对我来说,处理InnerExceptions的"母巢"以获取数据库提供程序在关闭连接之前发出的真实消息(在此消息时连接处于活动状态!)非常有用。或者,如果可能,只需使用允许您检查与正在进行的TSQL操作相关的任何错误的外部工具监视与数据库之间的事务(例如SQL Server Profiler)。

在我的情况下,场景是这样的:2个相同程序的实例(它是Windows服务),这些实例将记录插入表中。有两个特点:

  • 对于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()

我的代码是:

People entry = new People();
entry.name = "ABCD";
_ctx.Set<People>().Add(entry);
await _ctx.SaveChangesAsync();

这种写法导致两个进程之间发生并发情况(特别是当表中有大约 5M 条记录时),这会导致 SQL 引擎解决一个请求并取消另一个请求。调用程序的解释是:“已经发生了一个异常,很可能是由于短暂故障引起的。如果您正在连接到 SQL Azure 数据库,请考虑使用 SqlAzureExecutionStrategy。
为了避免问题,我不得不放弃恢复新记录分配的增量 ID,将表视为堆栈,并使用以下方法将写操作减少为直接插入操作:
await _ctx.Database.ExecuteSqlCommandAsync("INSERT INTO ....");

另一种方法是通过两个不涉及 EF TSQL 解析器的写操作来优化操作,并检索分配给最后添加记录的标识符。


3

当我尝试使用登录信息连接数据库时,如果该登录信息在数据库中没有关联的用户,则会出现此错误。


3

这可能是由于TLS设置引起的问题。默认情况下,.net 4.5框架不支持tls 1.2,并且新SQL数据库不兼容旧的tls版本。因此,要么在您的计算机上禁用tls 1.0、1.1,要么升级到.net 4.6.2。


我们最近切换到了Windows Server 2016,它也是一个Web服务器,管理员们运行了IISCrypt工具来修改Windows和IIS使用的密码。他们在禁用方面非常激进。 幸运的是,该服务器只有几天的历史,我意识到了发生了什么变化。不用说,你的回答恰好是正确的答案。 谢谢 - Salizar Marxx

2
在我的情况下,这个bug是由于在查询执行过程中因缺少await而在上下文中进行了处理造成的。

0
如果您的数据库是本地的,比如说一个WebAPI,有时候您必须提供数据源=localhost而不是IP地址。 我们遇到了这样的情况,使用一些VPS,如果不将数据源设置为localhost就会出现错误。 因此,如果其他人也遇到了这个问题,这可能会对他有所帮助。

这听起来像是另一个问题,与 SQL 连接没有直接关系,更像是 VPS 的问题。 - Zapnologica
是的,我同意。我只是想指出可能是与服务器连接的另一个问题。 - GenTech

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接