2013-06-04 35 views
16

私のアプリケーションは自分のサーバー上で動作しています。このアプリケーションの問題点は、毎日私が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はSqlExceptionが発生することがあります:タイムアウトがタイムアウトしました

  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) 
+1

はなぜ?実行には時間がかかりすぎたのでそれを最適化する。提供された詳細でこの質問に答えることは不可能です。投票を終了する。 – usr

+0

*** https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.commandtimeout.aspx*** 'CommandTimeout'を使用して解決策を得ましたか? – Kiquenet

答えて

20

実行がタイムアウトする理由を理解するには、サーバー側でこれを調べる必要があります。サーバーにタイムアウトがないことに注意してください。タイムアウトは、デフォルトの30秒がSqlCommand.CommandTimeoutの場合に発生します。

リソースは、Waits and Queuesです。これは、SQL Serverのパフォーマンスのボトルネックを診断する方法です。タイムアウトの実際の原因に基づいて、適切な処置をとることができます。遅い実行(悪い計画)やブロッキングを扱っているかどうかを最優先に確立する必要があります。

もし私が推測するならば、私はIF EXISTS... UPDATEという不健康なパターンが根本的な原因であると言います。このパターンは正しくないため、並行処理で障害が発生します。 IF EXISTSを同時に実行している2つの同時トランザクションは、両方とも同じ結論になり、と試みると、INSERTまたはUPDATEになります。データベース内に存在する制約条件によっては、デッドロック(幸運なケース)または書き込み不能(不運なケース)で終わる可能性があります。しかし、適切な調査だけが実際の根本原因を明らかにするであろう。 auto-growth eventsのようにまったく違うものかもしれません。

手順では、CATCHブロックも誤って処理されています。 常にを指定する必要があります。XACT_STATE()をチェックすると、CATCHブロックの実行時にトランザクションがすでにロールバックされている可能性があります。また、トランザクションの名前付けに何が期待されているのか明確ではありません。これは、セーブポイントと名前のついたトランザクションを混乱させることが多いことがよくある間違いです。正しいパターンについては、Exception Handling and Nested Transactionsを参照してください。関連CommandTimeout 0〜(。すなわち無限)

  1. 変更:ここで編集

    はこれを調査するために可能な方法です。

  2. Blocked Process Report Event
  3. のために30秒(旧CommandTimeoutの)
  4. にプロファイラでモニタを、それを設定し、blocked process thresholdを有効にプロファイラが任意のレポートのイベントを生成する場合、ワークロード
  5. を参照してください起動し
  6. 。そうであれば、原因を特定します。

これらのアクションによって、タイムアウトが発生するたびにブロックされたプロセスレポートが生成されます。アプリケーションは、ブロッキングが削除されるまで待つことを続行します。ブロッキングがlive-lockによって引き起こされた場合、それは永遠に待機します。

+1

クエリの遅い部分はどの部分にあってもかまいません。根本的な原因は何でもかまいません。私はその質問が答えられないと考えます。 +1 – usr

+0

@usr、私は、このSQLだけをこのエラーをスローしない大規模で大きなクエリをたくさん持っています。私はこのSPに何か間違いがあると信じています。私は実行が特別なものを挿入したり更新していると思う。データベースには索引付けはなく、表には800レコードのみが含まれています。何が必要なのですか? – user960567

+0

IF EXISTS ... UPDATE代替:['MERGE'](http://technet.microsoft.com/en-us/library/bb510625.aspx)。 '[UniqueID]'には(クラスタ化された?)インデックスがなければなりません( 'VARCHAR(500) 'でもそうです)。 –

6

です:

Connect Timeout=200; pooling='true'; Max Pool Size=200 

データの多くは、あなたがまたタイムアウトを増やすことができますがあればあなたはまた、

myCom.CommandTimeout = 200を設定することができます200秒から600秒の間である。

これをweb.configでも編集します。

THIS doccumentに従ってください。

+3

-1それを500に変えて1000にするなど... –

+0

@RemusRusanu what ???私はあなたのコメントを理解しませんでした。 – Freelancer

+5

私は彼が手順が長すぎるということは問題だと言っていると思うし、タイムアウトを増やすことは実際に問題に対処していない。 –

1

これは、パラメータスニッフィングのために発生します。したがって、ストアドプロシージャ内で宣言されたローカル変数を使用してください。適切に使用してください。

InVar1 @宣言...

.....条件= Invar1

関連する問題