我的服务器上运行了应用程序。这个应用程序的问题是每天我得到近10-20,System.Data.SqlClient.SqlException Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding
只有我的一个SP。这是我的SP,
ALTER PROCEDURE [dbo].[Insertorupdatedevicecatalog]
(@OS NVARCHAR(50)
,@UniqueID VARCHAR(500)
,@Longitude FLOAT
,@Latitude FLOAT
,@Culture VARCHAR(10)
,@Other NVARCHAR(200)
,@IPAddress VARCHAR(50)
,@NativeDeviceID VARCHAR(50))
AS
BEGIN
DECLARE @OldUniqueID VARCHAR(500) = '-1';
SELECT @OldUniqueID = [UniqueID] FROM DeviceCatalog WHERE (@NativeDeviceID != '' AND [NativeDeviceID] = @NativeDeviceID);
BEGIN TRANSACTION [Tran1]
BEGIN TRY
IF EXISTS(SELECT 1 FROM DeviceCatalog WHERE [UniqueID] = @UniqueID)
BEGIN
UPDATE DeviceCatalog
SET [OS] = @OS
,[Location] = geography::STGeomFromText('POINT(' + CONVERT(VARCHAR(100 ), @Longitude) + ' ' + CONVERT(VARCHAR(100), @Latitude) + ')', 4326)
,[Culture] = @Culture
,[Other] = @Other
,[Lastmodifieddate] = Getdate()
,[IPAddress] = @IPAddress
WHERE [UniqueID] = @UniqueID;
END
ELSE
BEGIN
INSERT INTO DeviceCatalog
([OS]
,[UniqueID]
,[Location]
,[Culture]
,[Other]
,[IPAddress]
,[NativeDeviceID])
VALUES (@OS
,@UniqueID
,geography::STGeomFromText('POINT(' + CONVERT(VARCHAR(100) ,@Longitude) + ' ' + CONVERT(VARCHAR(100), @Latitude) + ')', 4326)
,@Culture
,@Other
,@IPAddress
,@NativeDeviceID);
IF(@OldUniqueID != '-1' AND @OldUniqueID != @UniqueID)
BEGIN
EXEC DeleteOldDevice @OldUniqueID, @UniqueID;
END
END
COMMIT TRANSACTION [Tran1];
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION [Tran1];
DECLARE @ErrorNumber nchar(5), @ErrorMessage nvarchar(2048);
SELECT
@ErrorNumber = RIGHT('00000' + ERROR_NUMBER(), 5),
@ErrorMessage = @ErrorNumber + ' ' + ERROR_MESSAGE();
RAISERROR (@ErrorMessage, 16, 1);
END CATCH
END
这个SP有什么问题吗?为什么我只在此SP中获得超时异常?这是Stack Trace,
System.Data.SqlClient.SqlException (0x80131904): Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding.
at System.Data.SqlClient.SqlConnection.OnError(SqlException exception, Boolean breakConnection)
at System.Data.SqlClient.TdsParser.ThrowExceptionAndWarning()
at System.Data.SqlClient.TdsParser.Run(RunBehavior runBehavior, SqlCommand cmdHandler, SqlDataReader dataStream, BulkCopySimpleResultSet bulkCopyHandler, TdsParserStateObject stateObj)
at System.Data.SqlClient.SqlCommand.FinishExecuteReader(SqlDataReader ds, RunBehavior runBehavior, String resetOptionsString)
at System.Data.SqlClient.SqlCommand.RunExecuteReaderTds(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, Boolean async)
at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior, RunBehavior runBehavior, Boolean returnStream, String method, DbAsyncResult result)
at System.Data.SqlClient.SqlCommand.InternalExecuteNonQuery(DbAsyncResult result, String methodName, Boolean sendToPipe)
at System.Data.SqlClient.SqlCommand.ExecuteNonQuery()
at App.Classes.DBLayer.Execute(SqlCommand command, Boolean executeNonQuery)
at App.Helpers.SQLHelper.GetResult(List`1 parameters, Boolean storedProcedure, String commandText, ResultType type)
at App.Helpers.SQLHelper.ExecuteNonQuery(List`1 parameters, Boolean storedProcedure, String commandText)
at App.Services.DeviceCatalogService.InsertOrUpdateDeviceCatalog(DeviceCatalog deviceCataLog)
at WebApplication1.Handlers.RegisterDevice.ProcessRequest(HttpContext context)
at System.Web.HttpApplication.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute()
at System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously)
答案 0 :(得分:26)
您需要在服务器端对此进行调查,以了解执行超时的原因。请注意,服务器没有超时,超时是由SqlCommand.CommandTimeout
上的默认30秒引起的。
一个好的资源是Waits and Queues,这是一种诊断SQL Server性能瓶颈的方法。根据超时的实际原因,可以采取适当的措施。你必须首先确定你是在处理缓慢的执行(一个糟糕的计划)还是阻止。
如果我冒险猜测,我会说IF EXISTS... UPDATE
的不健康模式是根本原因。此模式不正确,将导致并发失败。同时执行IF EXISTS
的两个并发事务将得出相同的结论,并且两个尝试INSERT
或UPDATE
。根据数据库中的退出约束,您最终可能会出现死锁(幸运案例)或丢失写入(不幸的情况)。但是,只有适当的调查才能揭示实际的根本原因。可能是完全不同的东西,比如auto-growth events。
您的程序也错误地处理了CATCH块。您必须始终检查XACT_STATE()
,因为在您的CATCH块运行时,事务可能已经回滚。还不清楚您对命名事务的期望是什么,这是我经常看到的常见错误,通常与使用保存点混淆命名事务相关联。有关正确的模式,请参阅Exception Handling and Nested Transactions。
修改强>
以下是调查此问题的可行方法:
CommandTimeout
更改为0(即无限)。blocked process threshold
,将其设置为30秒(前CommandTimeout)如果超时是由阻塞引起的,那么每次超时都会导致“阻止进程报告”事件。您的应用程序将继续等待,直到阻止被删除,如果阻止是由live-lock引起的,那么它将永远等待。
答案 1 :(得分:8)
将此行添加到您的连接字符串中:
Connect Timeout=200; pooling='true'; Max Pool Size=200
您也可以设置myCom.CommandTimeout = 200
如果有大量数据,您还可以将超时秒数从200秒增加到600秒。
也可以在web.config中编辑它。
关注THIS doccument。
答案 2 :(得分:1)
这可能是因为参数嗅探而发生的。所以只需使用在存储过程中声明的局部变量。并适当地使用它们。
宣布@ InVar1 ......
.....
where condition = @Invar1
答案 3 :(得分:1)
可能 OPTIMIZE FOR 或 WITH RECOMPILE 提示解决了SQL Exception Timeout问题。
本文教导如何实现它并解释"参数嗅探"的问题: