次のsprocは、テーブルに行を挿入し、対応するテーブルのPKに使用されるランダムIDを生成しようとします。ランダムに生成されたIDとの衝突は、プロシージャが再試行され/再度呼び出されるcatchブロックで処理されます。ロックが長期間維持されるので、これには長い時間がかかり、デッドロックが発生します。再試行の直前にデッドロックを解放する方法があるので、他のスレッドがPKインデックスのロックに成功することができる短いウィンドウがありますか?再試行されたINSERTによるデッドロック
CREATE PROCEDURE addPerson
(
@FirstName nvarchar(100),
@LastName nvarchar(100)
)
AS
BEGIN
SET NOCOUNT ON;
DECLARE @PersonId int
-- generate random PersonId
-- this sproc can generate ids that already exist in the table
EXEC generateRandomPersonId @[email protected] OUTPUT
BEGIN TRY
INSERT INTO [dbo].[Persons]
(
PersonId,FirstName,LastName
)
VALUES
(
@PersonId,@FirstName,@LastName
)
BEGIN CATCH
--
-- HOW TO RELEASE LOCKS HERE that are still held
-- for the previous INSERT statement?
--
DECLARE @ErrorNumber int, @ErrorMessage nvarchar(2048)
SELECT @ErrorNumber=ERROR_NUMBER(),
@ErrorMessage=ERROR_MESSAGE()
-- if a race condition happened and
-- PersonId happened to be picked already, retry all over again
IF (@ErrorNumber = 2601 OR @ErrorNumber = 2627 AND CHARINDEX(N'PK_Persons_PersonId', @ErrorMessage) > 0)
BEGIN
--
-- RETRYING HERE participates in a high possibility and
-- occurrence of deadlocks
--
EXEC addPerson @FirstName,@LastName
END
ELSE
-- some other error, rethrow it
EXEC rethrowError
END
END CATCH
END
GO
は、商業用にこれですか生産環境製品? – danihp
一意の制約違反に対していくつかのエラーコードが存在するのはどうしてですか?私はSQLサーバーをまったく知りません、ただ好奇心が強い – fge
[トランザクション]を使用しない理由(http://beyondrelational.com/blogs/nakul/archive/2011/02/24/exception-handling-in-t-sql) try-catch-underappreciated-features-of-microsoft-sql-server.aspx)? 'try'の前にトランザクションを開始し、comment_を書く場所をロールバックします。 – danihp