加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net – 偶尔获取SqlException:超时过期

发布时间:2020-12-15 23:34:34 所属栏目:asp.Net 来源:网络整理
导读:我的应用程序在我的服务器上运行.这个应用程序的问题是,我每天接近10-20,System.Data.SqlClient.SqlException超时过期.在完成操作或服务器之前经过的超时时间没有仅响应我的一个SP.这是我的SP, ALTER PROCEDURE [dbo].[Insertorupdatedevicecatalog] (@OS NV
我的应用程序在我的服务器上运行.这个应用程序的问题是,我每天接近10-20,System.Data.SqlClient.SqlException超时过期.在完成操作或服务器之前经过的超时时间没有仅响应我的一个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),@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,Boolean returnStream,Boolean async)
   at System.Data.SqlClient.SqlCommand.RunExecuteReader(CommandBehavior cmdBehavior,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,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)

解决方法

您需要在服务器端进行调查,以了解为什么执行超时.请注意,服务器没有超时,超时是由 SqlCommand.CommandTimeout默认30秒引起的.

一个很好的资源是Waits and Queues,它是一种诊断SQL Server性能瓶颈的方法.根据超时的实际原因,可以采取适当的措施.您必须首先确定您是否处理缓慢的执行(坏计划)或阻止.

如果我冒昧猜测,我会说IF IFISIS UPDATE的不正常模式是根本原因.此模式不正确并将导致并发故障.同时执行IF EXISTS的两个并发事务将同时得出相同的结论,并尝试进行INSERT或UPDATE.根据数据库中的现有限制,您可能会遇到死锁(幸运案例)或丢失的写入(不幸的情况).但是,只有适当的调查才能揭示实际的根本原因.可能是一个完全不同的东西,比如auto-growth events.

您的程序也错误地处理CATCH块.您必须始终检查XACT_STATE(),因为您的CATCH块运行时可能已经回滚事务.也不清楚您对命名事务的期望,这是我常常遇到的常见错误,常常与命名事务与保存点混淆.对于正确的模式,请参阅Exception Handling and Nested Transactions.

编辑

这是一种可能的方式来调查这一点:

>将相关CommandTimeout更改为0(即无限大).
>启用blocked process threshold,设置为30秒(前一个CommandTimeout)
>在Profiler中监视Blocked Process Report Event
>开始你的工作量
>查看Profiler是否生成任何报告事件.如果这样做,他们会确定原因.

如果超时是由于阻塞引起的,那么每次收到超时时,这些操作将导致“阻止进程报告”事件.您的应用程序将继续等待,直到阻止被移除,如果阻塞是由live-lock造成的,那么它将永远等待.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读