我的服务器上正在运行应用程序。此应用程序的问题在于,每天我将获得近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,
System.Data.SqlClient.SqlException Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding
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中收到超时异常?这是堆栈跟踪,
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)
您需要在服务器端对此进行调查,以了解执行超时的原因。请注意,服务器没有超时,该超时是由上默认的30秒引起的SqlCommand.CommandTimeout。
SqlCommand.CommandTimeout
Waits和Queues是一个很好的资源,它是一种诊断SQL Server性能瓶颈的方法。根据超时的实际原因,可以采取适当的措施。您必须首先确定是要处理执行缓慢(不好的计划)还是阻塞。
如果我大胆猜测,我会说的不健康模式IF EXISTS... UPDATE是根本原因。此模式不正确,并发会导致失败。同时执行的两个并发事务IF EXISTS都将得出相同的结论,并且 都将 尝试执行INSERT或UPDATE。根据数据库中现有的约束,您可能会遇到死锁(幸运的情况)或丢失的写入(不幸的情况)。但是,只有进行适当的调查才能揭示出实际的根本原因。可能完全不同,例如自动增长事件。
IF EXISTS... UPDATE
IF EXISTS
INSERT
UPDATE
您的过程还错误地处理了CATCH块。您必须 始终 检查,XACT_STATE()因为在您的CATCH块运行时可能已经回滚了该事务。也不清楚您对事务命名的期望,这是我经常看到的与将命名事务与保存点混淆有关的常见错误。
XACT_STATE()