如何模拟数据库连接超时

Posted

技术标签:

【中文标题】如何模拟数据库连接超时【英文标题】:How to simulate a DB connection timeout 【发布时间】:2014-11-05 19:45:05 【问题描述】:

我们处于某些连接超时(可能)的情况,如果与 SQL 的连接超时,我们需要以某种方式处理代码,我知道使用 WAITFORDELAY 可以轻松模拟命令超时,但是如何你会模拟连接超时吗?

【问题讨论】:

【参考方案1】:

我只是设法模拟了一个连接超时

第一次在你的 sql server 上执行以下查询(我是在 ssms 中完成的)

ALTER DATABASE my_Test_DB SET SINGLE_USER;

从 Visual Studio 启动以下代码

namespace TimeOut_Test_Project_ASP

    public partial class _Default : System.Web.UI.Page
    
        protected void Page_Load(object sender, EventArgs e)
        
            string cs = "Data Source=ServerName;Initial Catalog=my_Test_DB; Integrated Security=SSPI;Connect Timeout=3";

            using (SqlConnection con = new SqlConnection(cs))
            
                SqlCommand cmd = new SqlCommand("SELECT * FROM dbo.TableName", con);

                con.Open();
                GridView1.DataSource = cmd.ExecuteReader();
                GridView1.DataBind();
            
        
    

错误堆栈

Server Error in '/' Application.

The wait operation timed out

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code. 

Exception Details: System.ComponentModel.Win32Exception: The wait operation timed out

Stack Trace: 


[Win32Exception (0x80004005): The wait operation timed out]

[SqlException (0x80131904): Connection Timeout Expired.  The timeout period elapsed during the post-login phase.  The connection could have timed out while waiting for server to complete the login process and respond; Or it could have timed out while attempting to create multiple active connections.  The duration spent while attempting to connect to this server was - [Pre-Login] initialization=309; handshake=1; [Login] initialization=0; authentication=1; [Post-Login] complete=2002; ]
   System.Data.SqlClient.SqlInternalConnection.OnError(SqlException exception, Boolean breakConnection, Action`1 wrapCloseInAction) +5340655
   System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning(TdsParserStateObject stateObj, Boolean callerHasConnectionLock, Boolean asyncClose) +244
   System.Data.SqlClient.TdsParserStateObject.ReadSniError(TdsParserStateObject stateObj, UInt32 error) +601
   System.Data.SqlClient.TdsParserStateObject.ReadSniSyncOverAsync() +256
   System.Data.SqlClient.TdsParserStateObject.TryReadNetworkPacket() +39
   System.Data.SqlClient.TdsParserStateObject.TryPrepareBuffer() +64
   System.Data.SqlClient.TdsParserStateObject.TryReadByte(Byte& value) +86
   System.Data.SqlClient.TdsParser.TryRun(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj, Boolean& dataReady) +222
   System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj) +69
   System.Data.SqlClient.SqlInternalConnectionTds.CompleteLogin(Boolean enlistOK) +30
   System.Data.SqlClient.SqlInternalConnectionTds.AttemptOneLogin(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean ignoreSniOpenTimeout, TimeoutTimer timeout, Boolean withFailover) +317
   System.Data.SqlClient.SqlInternalConnectionTds.LoginNoFailover(ServerInfo serverInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString connectionOptions, SqlCredential credential, TimeoutTimer timeout) +891
   System.Data.SqlClient.SqlInternalConnectionTds.OpenLoginEnlist(TimeoutTimer timeout, SqlConnectionString connectionOptions, SqlCredential credential, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance) +307
   System.Data.SqlClient.SqlInternalConnectionTds..ctor(DbConnectionPoolIdentity identity, SqlConnectionString connectionOptions, SqlCredential credential, Object providerInfo, String newPassword, SecureString newSecurePassword, Boolean redirectedUserInstance, SqlConnectionString userConnectionOptions, SessionData reconnectSessionData) +518
   System.Data.SqlClient.SqlConnectionFactory.CreateConnection(DbConnectionOptions options, DbConnectionPoolKey poolKey, Object poolGroupProviderInfo, DbConnectionPool pool, DbConnection owningConnection, DbConnectionOptions userOptions) +278
   System.Data.ProviderBase.DbConnectionFactory.CreatePooledConnection(DbConnectionPool pool, DbConnection owningObject, DbConnectionOptions options, DbConnectionPoolKey poolKey, DbConnectionOptions userOptions) +38
   System.Data.ProviderBase.DbConnectionPool.CreateObject(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection) +732
   System.Data.ProviderBase.DbConnectionPool.UserCreateRequest(DbConnection owningObject, DbConnectionOptions userOptions, DbConnectionInternal oldConnection) +85
   System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, UInt32 waitForMultipleObjectsTimeout, Boolean allowCreate, Boolean onlyOneCheckConnection, DbConnectionOptions userOptions, DbConnectionInternal& connection) +1057
   System.Data.ProviderBase.DbConnectionPool.TryGetConnection(DbConnection owningObject, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal& connection) +78
   System.Data.ProviderBase.DbConnectionFactory.TryGetConnection(DbConnection owningConnection, TaskCompletionSource`1 retry, DbConnectionOptions userOptions, DbConnectionInternal oldConnection, DbConnectionInternal& connection) +196
   System.Data.ProviderBase.DbConnectionInternal.TryOpenConnectionInternal(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) +146
   System.Data.ProviderBase.DbConnectionClosed.TryOpenConnection(DbConnection outerConnection, DbConnectionFactory connectionFactory, TaskCompletionSource`1 retry, DbConnectionOptions userOptions) +16
   System.Data.SqlClient.SqlConnection.TryOpenInner(TaskCompletionSource`1 retry) +94
   System.Data.SqlClient.SqlConnection.TryOpen(TaskCompletionSource`1 retry) +110
   System.Data.SqlClient.SqlConnection.Open() +96
   First_Project_ASP._Default.Page_Load(Object sender, EventArgs e) in D:\c# Projects\First Project ASP\First Project ASP\Default.aspx.cs:22
   System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +51
   System.Web.UI.Control.OnLoad(EventArgs e) +92
   System.Web.UI.Control.LoadRecursive() +54
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +772

将您的数据库重新设置为多用途模式

ALTER DATABASE [my_Test_DB] SET MULTI_USER;

【讨论】:

我怀疑这是否是 SQL 连接超时,因为在您的情况下连接确实建立到 SQL,但是命令对象由于锁定而超时。我正在寻找 SQL 级别的超时在发送命令之前首先尝试建立与 SQL 的连接。 @MurtazaMandvi 你是对的,这不是连接超时,而是查询超时错误,现在看看,我 101% 确定它是连接超时,因为我已将数据库更改为单个在我启动我的应用程序代码之前的用户模式。它尝试打开连接并在 3 秒后超时,因为我已在连接字符串中设置了 3 秒的属性。【参考方案2】:

看到this comment后,我萌生了尝试连接错误主机的想法,并且成功了。

保持用户名、数据库等正常,但将“host”参数更改为您可以控制的有效 URL/IP,但这样用户名和密码将不起作用。

连接将超时。

这样,您无需以任何方式更改您的数据库,因此非常棒。

也可以使用其他不正确的连接参数,例如数据库名称。

【讨论】:

【参考方案3】:

您也可以尝试将超时设置为一秒,看看是否会引发超时异常。请注意,1 是您可以设置的最低值。添加到您的连接字符串“Connection Timeout=1;”。请注意,这是一个 CONNECTION 超时,而不是查询超时,这完全是另一回事,并且未在连接字符串中设置。请注意,如果在 1 秒内建立连接,这可能会或可能不会实际模拟它。

我还尝试在尝试建立连接之前从我的开发机器上断开网络电缆。

【讨论】:

有时响应可能会在几毫秒内返回,因此它不会总是 100% 模拟超时场景

以上是关于如何模拟数据库连接超时的主要内容,如果未能解决你的问题,请参考以下文章

iOS 模拟器连接超时

我如何模拟慢速网络连接[重复]

Charles模拟手机应用网络超时

如何在本地端口上模拟网络延迟?

如何设置数据库的连接数和连接超时时间

如何设置数据库的连接数和连接超时时间