サーバーでアプリケーションを実行しています。このアプリケーションの問題は、毎日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の1つだけ。これが私の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でのみタイムアウト例外が発生するのはなぜですか?スタックトレースは次のとおりです。
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)
サーバー側でこれを調査し、実行がタイムアウトする理由を理解する必要があります。サーバーにはタイムアウトがないことに注意してください。タイムアウトは、 _SqlCommand.CommandTimeout
_ のデフォルトの30秒によって発生します。
適切なリソースは Waits and Queues です。これは、SQL Serverのパフォーマンスのボトルネックを診断する方法です。タイムアウトの実際の原因に基づいて、適切なアクションを実行できます。遅い実行(悪い計画)を処理しているかブロックしているかをまず確認する必要があります。
推測するなら、_IF EXISTS... UPDATE
_の不健康なパターンが根本的な原因だと思います。このパターンは正しくないため、同時実行ではエラーが発生します。 _IF EXISTS
_を同時に実行する2つの同時トランザクションは、両方とも同じ結論に達し、bothはINSERT
またはUPDATE
を試行します。データベースの既存の制約に応じて、デッドロック(ラッキーケース)または失われた書き込み(アンラッキーケース)になる可能性があります。ただし、適切な調査のみが実際の根本原因を明らかにします。 auto-growth events のように、まったく異なるものになる可能性があります。
また、プロシージャはCATCHブロックを誤って処理しています。 alwaysをチェックする必要があります XACT_STATE()
をチェックするブロックが実行されます。また、トランザクションに名前を付けることから何を期待するかも明確ではありません。これは、名前付きトランザクションをセーブポイントと混同することに関連するよくある間違いです。正しいパターンについては、 例外処理とネストされたトランザクション を参照してください。
編集
これを調査する可能な方法は次のとおりです。
CommandTimeout
を0(無限)に変更します。blocked process threshold
_ を有効にし、30秒に設定します(以前のCommandTimeout)これらのアクションにより、タイムアウトがブロックによるものである場合、タイムアウトが発生するたびに「ブロックされたプロセスレポート」イベントが発生します。アプリケーションは、ブロックが解除されるまで待機し続けます。ブロックの原因が live-lock である場合、アプリケーションは永久に待機します。
接続文字列に次の行を追加します。
Connect Timeout=200; pooling='true'; Max Pool Size=200
myCom.CommandTimeout = 200
も設定できます
大量のデータがある場合は、タイムアウト秒数を200秒から600秒に増やすこともできます。
これもweb.configで編集します。
[〜#〜] this [〜#〜] ドキュメントに従ってください。
これは、パラメータスニッフィングが原因で発生する可能性があります。したがって、ストアドプロシージャ内で宣言されたローカル変数を使用するだけです。それらを適切に使用します。
@ InVar1を宣言する...
.....
where condition = @ Invar1
たぶんOPTIMIZE FORまたはWITH RECOMPILEヒントがSQL例外タイムアウトの問題を解決する。
この記事では、その実装方法を説明し、「パラメータスニッフィング」の問題について説明します。