2013-06-04 43 views
16

Tôi có ứng dụng đang chạy trên máy chủ của mình. Vấn đề với ứng dụng này là hàng ngày tôi nhận được gần 10-20, System.Data.SqlClient.SqlException Timeout expired. The timeout period elapsed prior to completion of the operation or the server is not responding chỉ một trong số SP của tôi. Đây là SP của tôi,Thỉnh thoảng Bắt SqlException: Thời gian chờ hết hạn

  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 

Có vấn đề gì với SP này không? Tại sao tôi nhận được ngoại lệ Timeout chỉ trong SP này? Đây là 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) 
+1

Tại sao? Vì việc thực hiện mất quá nhiều thời gian. Tối ưu hóa nó. Không thể trả lời câu hỏi này với các chi tiết được cung cấp. Bỏ phiếu để đóng. – usr

+0

bạn có nhận được giải pháp sử dụng *** https: //msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand.commandtimeout.aspx*** 'CommandTimeout' không? – Kiquenet

Trả lời

20

Bạn cần điều tra điều này ở phía máy chủ để hiểu lý do tại sao thời gian thực hiện hết. Lưu ý rằng máy chủ không có thời gian chờ, thời gian chờ được gây ra bởi 30 giây mặc định trên SqlCommand.CommandTimeout.

Tài nguyên tốt là Waits and Queues, là phương pháp để chẩn đoán tắc nghẽn hiệu suất với SQL Server. Dựa trên nguyên nhân thực sự của thời gian chờ, hành động thích hợp có thể được thực hiện. Bạn phải thiết lập đầu tiên và quan trọng nhất cho dù bạn đang đối phó với thực hiện chậm (một kế hoạch xấu) hoặc chặn.

Nếu tôi muốn mạo hiểm đoán, tôi sẽ nói rằng mẫu không lành mạnh của IF EXISTS... UPDATE là nguyên nhân gốc rễ. Mẫu này không đúng và sẽ gây ra lỗi theo sự đồng thời. Hai giao dịch đồng thời thực thi IF EXISTS đồng thời cả hai sẽ đạt được cùng một kết luận và cả hai cố gắng INSERT hoặc UPDATE. Tùy thuộc vào các ràng buộc thoát trong cơ sở dữ liệu, bạn có thể kết thúc với một bế tắc (trường hợp may mắn) hoặc với một ghi bị mất (trường hợp không may mắn). Tuy nhiên, chỉ có điều tra thích hợp mới tiết lộ nguyên nhân gốc rễ thực sự. Có thể là một cái gì đó hoàn toàn khác, như auto-growth events.

Quy trình của bạn cũng đang xử lý không chính xác khối CATCH. Bạn phải luôn luôn kiểm tra XACT_STATE() vì giao dịch có thể đã được khôi phục vào thời điểm khối CATCH của bạn chạy. Cũng không rõ những gì bạn mong đợi từ việc đặt tên cho giao dịch, đây là một lỗi phổ biến mà tôi thấy thường liên quan đến các giao dịch có tên nhầm lẫn với các điểm lưu trữ. Để có mẫu chính xác, hãy xem Exception Handling and Nested Transactions.

Sửa

Dưới đây là một cách tốt để điều tra này:

  1. Thay đổi liên quan CommandTimeout-0 (. Tức là vô hạn).
  2. Kích hoạt tính năng blocked process threshold, đặt nó là 30 giây (cựu CommandTimeout)
  3. Monitor trong Profiler cho Blocked Process Report Event
  4. Bắt đầu khối lượng công việc của bạn
  5. Xem nếu Profiler sản xuất bất kỳ sự kiện báo cáo. Nếu có, họ sẽ xác định nguyên nhân.

Những hành động này sẽ gây ra sự kiện 'báo cáo quá trình bị chặn' mỗi khi bạn có thời gian chờ, nếu thời gian chờ gây ra bằng cách chặn. Ứng dụng của bạn sẽ tiếp tục chờ cho đến khi chặn được xóa, nếu việc chặn được gây ra bởi một số live-lock thì nó sẽ chờ mãi mãi.

+1

Phần chậm của truy vấn có thể ở bất kỳ phần nào. Nguyên nhân gốc rễ có thể là bất cứ điều gì. Tôi coi câu hỏi là không thể trả lời được. +1 – usr

+0

@usr, tôi có nhiều truy vấn rộng lớn và không ném lỗi này, chỉ có SQL này. Tôi tin rằng có điều gì đó sai trái trong SP này. Tôi nghĩ rằng việc thực hiện được chèn hoặc cập nhật không có gì đặc biệt. Không có chỉ mục trong cơ sở dữ liệu và bảng chỉ bao gồm 800 bản ghi. Bạn cần gì khác? – user960567

+0

'IF EXISTS ... UPDATE' thay thế: [' MERGE'] (http://technet.microsoft.com/en-us/library/bb510625.aspx). Bạn phải có một chỉ mục (clustered?) Trên '[UniqueID]' (có, ngay cả tại 'VARCHAR (500)'). –

6

Thêm dòng này vào chuỗi kết nối của bạn:

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

Bạn có thể đặt myCom.CommandTimeout = 200 cũng

Nếu số lượng lớn các dữ liệu đó bạn cũng có thể tăng thời gian chờ giây từ 200 đến 600 giây.

Chỉnh sửa điều này trong web.config.

Làm theo THIS tài liệu.

+3

-1 rồi thay đổi 500 sau đó thành 1000 và cứ thế ... –

+0

@RemusRusanu gì ??? Tôi không hiểu bình luận của bạn. – Freelancer

+5

Tôi nghĩ rằng anh ấy nói rằng quá trình mất quá nhiều thời gian là vấn đề và việc tăng thời gian chờ không thực sự giải quyết được vấn đề. –

1

Điều này có thể xảy ra do tham số đánh hơi. Vì vậy, chỉ cần sử dụng các biến cục bộ, khai báo trong proc được lưu trữ. và sử dụng chúng một cách thích hợp.

Declare @ InVar1 ...

.....

nơi condition = @ Invar1

Các vấn đề liên quan