Azure无服务器数据库连接未返回40613错误码问题咨询
为什么应用连接Azure无服务器数据库时捕获不到40613错误码?
我之前处理Azure无服务器SQL数据库时也碰到过一模一样的问题——SSMS能正常拿到40613错误码,但应用里只抛出超时异常,根本抓不到这个关键错误。核心原因主要有两个,咱们逐个拆解:
核心原因分析
1. 连接超时设置太短
Azure无服务器数据库从暂停状态恢复通常需要10-20秒(甚至更久,取决于数据库大小),但SqlConnection的默认连接超时只有15秒。这就导致:数据库还没来得及返回40613错误,应用的连接请求就已经超时了,直接抛出TimeoutException,根本轮不到SqlException被捕获。
而SSMS的默认连接超时一般是30秒以上,所以它能等到数据库返回40613错误。
2. 恢复过程中的底层连接异常
在数据库恢复初期,可能会出现TCP连接中断、资源暂时不可用等情况,这时候ADO.NET可能直接抛出TimeoutException,而不是封装成带错误码的SqlException。
解决方案
针对这两个问题,我们可以通过调整连接配置和优化重试逻辑来解决:
第一步:延长连接超时时间
在你的连接字符串里增加Connection Timeout=60(设置为60秒足够覆盖大部分恢复场景),给数据库足够的时间返回错误码:
Server=tcp:your-server.database.windows.net,1433;Initial Catalog=your-db;Persist Security Info=False;User ID=your-user;Password=your-pass;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=60;
第二步:优化异常捕获与重试逻辑
不仅要捕获SqlException的40613,还要处理TimeoutException,同时加入重试机制(恢复是个过程,一次请求可能不够)。另外,Azure SQL恢复相关的错误码不止40613,建议一起捕获:
public async Task<IDbConnection> GetConnectionAsync() { const int maxRetryAttempts = 3; const int retryDelayMs = 5000; // 每次重试等待5秒,给数据库恢复时间 int attempt = 0; while (attempt < maxRetryAttempts) { var connection = new SqlConnection(_connectionString); try { await connection.OpenAsync(); return connection; } catch (SqlException ex) { // 捕获所有Azure SQL恢复/暂停相关的错误码 var recoverableErrors = new HashSet<int> { 40613, 40197, 4060, 10928, 10929 }; if (recoverableErrors.Contains(ex.Number)) { attempt++; await Task.Delay(retryDelayMs); continue; } // 非恢复类SQL异常,直接抛出 throw; } catch (TimeoutException) { // 超时也视为可能的恢复中状态,进行重试 attempt++; await Task.Delay(retryDelayMs); continue; } finally { // 如果连接没成功打开,确保关闭释放资源 if (connection.State != ConnectionState.Open) { connection.Close(); } } } throw new InvalidOperationException("数据库经过多次重试后仍无法建立连接,请检查数据库状态"); }
补充说明
- 如果你必须使用同步方法(
Open()而非OpenAsync()),同步超时会抛出SqlException,错误码为-2,你也可以把这个错误码加入到可重试的集合中。 - 可以考虑使用Polly这类重试库来更优雅地处理重试逻辑,避免自己编写循环代码。
内容的提问来源于stack exchange,提问作者Lasse Klitgaard
相关产品推荐
相关产品推荐

