2011-10-27 168 views
1

我們運行一個小網站,我們使用標準的SqlMembershipProvider,並且我們有一個標準的CreateUserWizard。事務死鎖SqlMembershipProvider.CreateUser()

我們得到了未處理的例外:

事務(進程ID XX)被死鎖的鎖資源與另一個過程和已被選作死鎖犧牲品。重新運行交易。

堆棧跟蹤爲

System.Web.Security.SqlMembershipProvider。 CREATEUSER(字符串的用戶名,密碼字符串,字符串電子郵件,字符串passwordQuestion,字符串passwordAnswer,布爾isApproved,對象providerUserKey,MembershipCreateStatus &狀態)

System.Web.UI.WebControls.CreateUserWizard。 嘗試創建用戶()

任何想法如何解決這個問題?

有SQL查詢是標準的事情:

ALTER PROCEDURE [dbo].[aspnet_Membership_CreateUser] 
    @ApplicationName      nvarchar(256), 
    @UserName        nvarchar(256), 
    @Password        nvarchar(128), 
    @PasswordSalt       nvarchar(128), 
    @Email         nvarchar(256), 
    @PasswordQuestion      nvarchar(256), 
    @PasswordAnswer       nvarchar(128), 
    @IsApproved        bit, 
    @CurrentTimeUtc       datetime, 
    @CreateDate        datetime = NULL, 
    @UniqueEmail       int  = 0, 
    @PasswordFormat       int  = 0, 
    @UserId         uniqueidentifier OUTPUT 
AS 
BEGIN 
    DECLARE @ApplicationId uniqueidentifier 
    SELECT @ApplicationId = NULL 

    DECLARE @NewUserId uniqueidentifier 
    SELECT @NewUserId = NULL 

    DECLARE @IsLockedOut bit 
    SET @IsLockedOut = 0 

    DECLARE @LastLockoutDate datetime 
    SET @LastLockoutDate = CONVERT(datetime, '17540101', 112) 

    DECLARE @FailedPasswordAttemptCount int 
    SET @FailedPasswordAttemptCount = 0 

    DECLARE @FailedPasswordAttemptWindowStart datetime 
    SET @FailedPasswordAttemptWindowStart = CONVERT(datetime, '17540101', 112) 

    DECLARE @FailedPasswordAnswerAttemptCount int 
    SET @FailedPasswordAnswerAttemptCount = 0 

    DECLARE @FailedPasswordAnswerAttemptWindowStart datetime 
    SET @FailedPasswordAnswerAttemptWindowStart = CONVERT(datetime, '17540101', 112) 

    DECLARE @NewUserCreated bit 
    DECLARE @ReturnValue int 
    SET @ReturnValue = 0 

    DECLARE @ErrorCode  int 
    SET @ErrorCode = 0 

    DECLARE @TranStarted bit 
    SET @TranStarted = 0 

    IF(@@TRANCOUNT = 0) 
    BEGIN 
     BEGIN TRANSACTION 
     SET @TranStarted = 1 
    END 
    ELSE 
     SET @TranStarted = 0 

    EXEC dbo.aspnet_Applications_CreateApplication @ApplicationName, @ApplicationId OUTPUT 

    IF(@@ERROR <> 0) 
    BEGIN 
     SET @ErrorCode = -1 
     GOTO Cleanup 
    END 

    SET @CreateDate = @CurrentTimeUtc 

    SELECT @NewUserId = UserId FROM dbo.aspnet_Users WHERE LOWER(@UserName) = LoweredUserName AND @ApplicationId = ApplicationId 
    IF (@NewUserId IS NULL) 
    BEGIN 
     SET @NewUserId = @UserId 
     EXEC @ReturnValue = dbo.aspnet_Users_CreateUser @ApplicationId, @UserName, 0, @CreateDate, @NewUserId OUTPUT 
     SET @NewUserCreated = 1 
    END 
    ELSE 
    BEGIN 
     SET @NewUserCreated = 0 
     IF(@NewUserId <> @UserId AND @UserId IS NOT NULL) 
     BEGIN 
      SET @ErrorCode = 6 
      GOTO Cleanup 
     END 
    END 

    IF(@@ERROR <> 0) 
    BEGIN 
     SET @ErrorCode = -1 
     GOTO Cleanup 
    END 

    IF(@ReturnValue = -1) 
    BEGIN 
     SET @ErrorCode = 10 
     GOTO Cleanup 
    END 

    IF (EXISTS (SELECT UserId 
        FROM dbo.aspnet_Membership 
        WHERE @NewUserId = UserId)) 
    BEGIN 
     SET @ErrorCode = 6 
     GOTO Cleanup 
    END 

    SET @UserId = @NewUserId 

    IF (@UniqueEmail = 1) 
    BEGIN 
     IF (EXISTS (SELECT * 
        FROM dbo.aspnet_Membership m WITH (UPDLOCK, HOLDLOCK) 
        WHERE ApplicationId = @ApplicationId AND LoweredEmail = LOWER(@Email))) 
     BEGIN 
      SET @ErrorCode = 7 
      GOTO Cleanup 
     END 
    END 

    IF (@NewUserCreated = 0) 
    BEGIN 
     UPDATE dbo.aspnet_Users 
     SET LastActivityDate = @CreateDate 
     WHERE @UserId = UserId 
     IF(@@ERROR <> 0) 
     BEGIN 
      SET @ErrorCode = -1 
      GOTO Cleanup 
     END 
    END 

    INSERT INTO dbo.aspnet_Membership 
       (ApplicationId, 
        UserId, 
        Password, 
        PasswordSalt, 
        Email, 
        LoweredEmail, 
        PasswordQuestion, 
        PasswordAnswer, 
        PasswordFormat, 
        IsApproved, 
        IsLockedOut, 
        CreateDate, 
        LastLoginDate, 
        LastPasswordChangedDate, 
        LastLockoutDate, 
        FailedPasswordAttemptCount, 
        FailedPasswordAttemptWindowStart, 
        FailedPasswordAnswerAttemptCount, 
        FailedPasswordAnswerAttemptWindowStart) 
     VALUES (@ApplicationId, 
        @UserId, 
        @Password, 
        @PasswordSalt, 
        @Email, 
        LOWER(@Email), 
        @PasswordQuestion, 
        @PasswordAnswer, 
        @PasswordFormat, 
        @IsApproved, 
        @IsLockedOut, 
        @CreateDate, 
        @CreateDate, 
        @CreateDate, 
        @LastLockoutDate, 
        @FailedPasswordAttemptCount, 
        @FailedPasswordAttemptWindowStart, 
        @FailedPasswordAnswerAttemptCount, 
        @FailedPasswordAnswerAttemptWindowStart) 

    IF(@@ERROR <> 0) 
    BEGIN 
     SET @ErrorCode = -1 
     GOTO Cleanup 
    END 

    IF(@TranStarted = 1) 
    BEGIN 
     SET @TranStarted = 0 
     COMMIT TRANSACTION 
    END 

    RETURN 0 

Cleanup: 

    IF(@TranStarted = 1) 
    BEGIN 
     SET @TranStarted = 0 
     ROLLBACK TRANSACTION 
    END 

    RETURN @ErrorCode 

END 

謝謝!

+0

交易死鎖在「小型網站」中並不常見,人們不會期望很多資源競爭。看看這篇文章是否能夠闡明你面臨的問題:http://social.msdn.microsoft.com/forums/en-US/sqldatabaseengine/thread/e0210b4f-61c4-41f3-a573-c5fe7ac33b5e –

+0

爭奪資源在我看來,這與流量無關,但網頁編程有多糟糕。 我將嘗試獲取線程談到的那些圖形。 – BCartolo

回答

1

有沒有人在編輯模式下SQL Server Management Studio中打開表:即:表鎖?

+0

沒有。不過謝謝你的回覆 – BCartolo

0

只需將@UserId設置爲新的GUID即可使用。

set @User = NEWID();