3

次のストアド プロシージャで断続的にデッドロックが発生します。1 分間に 1 回実行されます。1年以上運用されており、通常このエラーは発生しませんが、時々発生します...環境の1つで1日に3〜5回例外をスローしています...それは他のインスタンスと同じ環境ですエラーをスローしていません。ストアド プロシージャは、一度に 1 回しか実行できないように作成されていますが、この方法は適切ではないのでしょうか?

エラーは次のとおりです。

System.Web.HttpUnhandledException: タイプ 'System.Web.HttpUnhandledException' の例外がスローされました。---> System.Data.SqlClient.SqlException: トランザクション (プロセス ID 60) が別のプロセスのロック リソースでデッドロックされ、デッドロックの犠牲者として選択されました。トランザクションを再実行します。

ストアド プロシージャは次のとおりです。

 SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[requestUpdate]
AS
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;

BEGIN TRAN
    DECLARE @StartDate datetime,
            @EndDate datetime,
            @Throttle bit,
            @Expired bit

    SELECT @Throttle = 0
    SELECT @Expired = 0

    SELECT TOP 1 @StartDate = uq.StartDate, @EndDate = uq.EndDate
      FROM UpdateQueue uq WITH(TABLOCK,XLOCK)
     ORDER BY ID DESC

    -- PREVENT ANOTHER REQUEST IF THIS SP HAS BEEN
    -- CALLED IN THE LAST FORTY SECONDS.
    IF DATEADD(SECOND,-40,GETDATE()) < @StartDate
    BEGIN
      SELECT @Throttle = 1
    END

    -- CREATE ANOTHER REQUEST IF THE CURRENT ONE
    -- HAS NOT COMPLETED IN THE LAST FIVE MINUTES.
    IF @StartDate <= DATEADD(MINUTE,-5,GETDATE())
    BEGIN
      SELECT @Expired = 1
    END

    -- HAS THE CURRENT REQUEST EXPIRED?
    IF @EndDate IS NULL AND @Expired = 1
    BEGIN
      INSERT INTO UpdateQueue (RequestID, StartDate) OUTPUT 'EXPIRED' AS Result, INSERTED.RequestID AS RequestID
      VALUES (NEWID(), GETDATE())
    END

    -- HAS THE CURRENT REQUEST COMPLETED AND YOU ARE NOT THROTTLING
    -- OR HAVE THERE NOT BEEN ANY REQUESTS YET?
    ELSE IF (@EndDate IS NOT NULL AND @Throttle = 0) OR @StartDate IS NULL
    BEGIN
      INSERT INTO UpdateQueue (RequestID, StartDate) OUTPUT 'STARTED' AS Result, INSERTED.RequestID AS RequestID
      VALUES (NEWID(), GETDATE())
    END

    -- Running
    ELSE
    BEGIN
      SELECT 'RUNNING' AS Result, NULL AS RequestID
    END

COMMIT
4

1 に答える 1

0

これは、接続が待機するよりも長く保持されている特定のロックの問題であると思われます. 接続がタイムアウトすると、SQL Server が待機を強制的に終了させ、着信ロックをデッドロックの犠牲者として強制終了するため、実行時間の長いトランザクションを強制終了するものがないと、ここでこれに遭遇します。

簡単に言うと、一部のプロセス (ここで詳しく説明したものではない) がテーブルをロックしているため、デッドロックが発生しています。

デッドロックが発生しているときに他に何が起こっているかを調べてください。実行中のバックアップがありますか、またはこのテーブルをロックする何か他のものがありますか?

于 2013-02-15T17:47:40.660 に答える