我在尝试连接数据库时遇到以下错误:
发生与网络相关或特定于实例的错误 建立与SQL Server的连接。找不到服务器或 无法访问。验证实例名称是否正确 SQL Server配置为允许远程连接。 (提供者:命名 管道提供程序,错误:40 - 无法打开与SQL Server的连接)
现在有时我得到这个错误,有时我不这样做,例如:当我第一次运行我的程序时,它成功打开连接,当我第二次运行时,我得到这个错误,下次我运行我的程序然后我不会得到错误。
当我尝试通过SSMS连接到同一个数据库服务器时,我能够成功连接,但我只在我的程序中遇到此网络问题。
数据库不在我的 LOCAL .Its AZURE 。
我的本地数据库没有出现此错误。
代码:
public class AddOperation
{
public void Start()
{
using (var processor = new MyProcessor())
{
for (int i = 0; i < 2; i++)
{
if(i==0)
{
var connection = new SqlConnection("Connection string 1");
processor.Process(connection);
}
else
{
var connection = new SqlConnection("Connection string 2");
processor.Process(connection);
}
}
}
}
}
public class MyProcessor : IDisposable
{
public void Process(DbConnection cn)
{
using (var cmd = cn.CreateCommand())
{
cmd.CommandText = "query";
cmd.CommandTimeout = 1800;
cn.Open();//Sometimes work sometimes dont
using (var reader = cmd.ExecuteReader(CommandBehavior.CloseConnection))
{
//code
}
}
}
}
所以我对两件事感到困惑:
1) ConnectionTimeout:我是否应该增加connectiontimeout并解决我的异常连接问题?
2)重试尝试策略:我应该实现如下的重试连接机制:
public static void OpenConnection(DbConnection cn, int maxAttempts = 1)
{
int attempts = 0;
while (true)
{
try
{
cn.Open();
return;
}
catch
{
attempts++;
if (attempts >= maxAttempts) throw;
}
}
}
我对上面两个选项感到困惑。
任何人都可以建议我处理这个问题的更好方法是什么?
答案 0 :(得分:5)
正如您可以阅读here,即使安装在Azure VM(IaaS)上的SQL Server,也建议使用重试逻辑。
故障处理:您的应用程序代码包括重试逻辑和 瞬态故障处理?包括适当的重试逻辑和瞬态 代码中的故障处理修复应该是通用的最佳方法 在本地和云中实践,无论是IaaS还是PaaS。如果 缺少这种特性,两者都可能出现应用问题 Azure VM中的Azure SQLDB和SQL Server,但在此方案中 后者被推荐超过前者。
建议使用增量重试逻辑。
从应用程序需要的应用程序块中实例化对象有两种基本方法。在第一种方法中,您可以显式实例化代码中的所有对象,如以下代码段所示:
var retryStrategy = new Incremental(5, TimeSpan.FromSeconds(1),
TimeSpan.FromSeconds(2));
var retryPolicy =
new RetryPolicy<SqlDatabaseTransientErrorDetectionStrategy>(retryStrategy);
在第二种方法中,您可以从配置数据中实例化和配置对象,如以下代码段所示:
// Load policies from the configuration file.
// SystemConfigurationSource is defined in
// Microsoft.Practices.EnterpriseLibrary.Common.
using (var config = new SystemConfigurationSource())
{
var settings = RetryPolicyConfigurationSettings.GetRetryPolicySettings(config);
// Initialize the RetryPolicyFactory with a RetryManager built from the
// settings in the configuration file.
RetryPolicyFactory.SetRetryManager(settings.BuildRetryManager());
var retryPolicy = RetryPolicyFactory.GetRetryPolicy
<SqlDatabaseTransientErrorDetectionStrategy>("Incremental Retry Strategy");
...
// Use the policy to handle the retries of an operation.
}
有关详细信息,请访问this文档。
答案 1 :(得分:3)
使用新版本的.NET(4.6.1或更高版本),然后利用内置的弹性功能:
ConnectRetryCount,ConnectRetryInterval和Connection Timeout。
答案 2 :(得分:2)
与远程服务通信的所有应用程序都对瞬态故障敏感。
如其他答案中所述,如果您的客户端程序使用.NET Framework类System.Data.SqlClient.SqlConnection连接到SQL数据库,请使用.NET 4.6.1或更高版本(或.NET Core)以便您可以使用其连接重试功能。
为SqlConnection对象构建连接字符串时,请协调以下参数之间的值:
ConnectRetryCount :默认值为1.范围是0到255。
ConnectRetryInterval :默认值为1秒。范围是1到60。
连接超时:默认为15秒。范围是0到2147483647。
具体而言,您选择的值应使以下等式为真:
Connection Timeout = ConnectRetryCount * ConnectionRetryInterval
现在,来到选项2,当您的应用程序具有自定义重试逻辑时,它将增加总重试次数 - 对于每次自定义重试,它将尝试ConnectRetryCount次。例如如果ConnectRetryCount = 3并且自定义重试= 5,它将尝试15次尝试。您可能不需要那么多次重试。
如果您只考虑自定义重试与连接超时:
连接超时通常是由于网络损耗 - 网络丢失率较高(例如,蜂窝或弱WiFi)或高流量负载。您可以选择在其中使用的最佳策略。
以下指南有助于解决瞬态错误:
答案 3 :(得分:1)
您使用的是SQL Express还是Workgroup Edition?如果是这样,服务器可能太忙而无法响应。
要排除网络问题,请在命令提示符下执行PING -t SqlServername
。每次ping都会回来,还是有些丢失?这可能是网络中断的指示,也可能导致此错误,如错误的交换机。如果它们所有丢失,那么(假设您的数据库连接有时可行),很可能某个地方的防火墙阻止了ping:如果找到该块并暂时取消阻止,它可能有助于诊断。 / p>
错误消息表明您正在使用命名管道。你是故意使用命名管道吗?对于大多数方案(包括Azure数据库),我建议在SQL Server配置管理器中启用TCP / IP并禁用命名管道。
取决于远方&#39;您的Azure数据库是因为路由器和防火墙有时会破坏Kerberos和/或相关时间的延迟。您可以通过使用连接字符串中的端口来避免这种情况,以避免到端口1434的往返来枚举实例。我假设您已经在使用FQDN。例如:server \ instance,port
答案 4 :(得分:1)
连接完全可能掉线。 &#34;分布式计算的谬误&#34; :)。 这可能是网络连接问题。可以在任何一端。
我建议:(假设您的计算机在Azure上启用了防火墙)
ping(服务器).database.windows.net
以上三项应该可以帮助您确定问题所在。
我认为您的重试逻辑很好。
关于你的问题
增加超时 只有当您确定您的查询需要很长时间时。如果对于简单插入,您必须增加超时问题,可能是网络连接。
重试逻辑 如上所述,它现在是您可以使用的框架的一部分,或者您创建的框架应该没问题。理想情况下,即使您确定连接和速度,重试逻辑也很不错。以防万一:)
答案 5 :(得分:1)
您应该增加超时,因为建立与SQL Server的连接所需的时间有很多步骤,因此第一次建立连接需要一些时间。建立连接后,将连接汇集在内存中,以便在后续查询中重复使用。
有关连接池的更多详细信息,请参阅以下链接: https://docs.microsoft.com/en-us/dotnet/framework/data/adonet/sql-server-connection-pooling
正如您所提到的那样,有时会产生此错误,并非总是如此,因此可能存在一些网络和连接因素。 SQL连接的默认超时为15秒。我想如果你把它改成30秒,它应该可以工作。
答案 6 :(得分:1)
考虑使用Polly。
您可以使用一段简单的代码,例如 -
RetryPolicy retryPolicy = Policy.Handle<Exception>()
.WaitAndRetry(3, retryAttempt =>
TimeSpan.FromSeconds(retryAttempt));
var result = retryPolicy.Execute(() => someClass.DoSomething());
这将最多重试该请求三次。