如何解决死锁问题

时间:2016-05-20 11:32:20

标签: sql-server stored-procedures deadlock

我们有一个插入/更新/删除的存储过程,我们遇到一个问题,即用户有时会遇到死锁并丢失数据,这是因为另一个用户或实例正在使用存储过程或表。 enter image description here

    CREATE TABLE [file].[ItemResourceFile](
    [ID] [int] IDENTITY(1,1) NOT NULL,
    [Item_ID] [int] NOT NULL,
    [ResourceFile_ID] [int] NOT NULL,
    [IsDefault] [bit] NOT NULL CONSTRAINT [DF_ItemResourceFile_IsDefault]  DEFAULT ((0)),
    [Description] [nvarchar](max) NULL,
    [DateTimeCreated] [datetime] NOT NULL CONSTRAINT [DF_ItemResourceFile_DateTimeCreated]  DEFAULT (getutcdate()),
    [DateTimeModified] [datetime] NOT NULL CONSTRAINT [DF_ItemResourceFile_DateTimeModified]  DEFAULT (getutcdate()),
    [CreatorUser_ID] [int] NOT NULL,
    [LastModifierUser_ID] [int] NOT NULL,
    [Status] [tinyint] NOT NULL CONSTRAINT [DF_ItemResourceFile_Status]  DEFAULT ((0)),
    [sequenceID] [int] NULL DEFAULT ('NULL'),
 CONSTRAINT [PK_ItemResourceFile] PRIMARY KEY CLUSTERED 
(
    [Item_ID] ASC,
    [ResourceFile_ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [FILE]
) ON [FILE] TEXTIMAGE_ON [FILE]

GO

/****** Object:  Index [IX_ItemResourceFile_ID]    Script Date: 20-May-16 13:25:56 ******/
CREATE UNIQUE NONCLUSTERED INDEX [IX_ItemResourceFile_ID] ON [file].[ItemResourceFile]
(
    [ID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [FILE]
GO

/****** Object:  Index [IX_ItemResourceFile_IsDefault]    Script Date: 20-May-16 13:25:56 ******/
CREATE UNIQUE NONCLUSTERED INDEX [IX_ItemResourceFile_IsDefault] ON [file].[ItemResourceFile]
(
    [Item_ID] ASC,
    [IsDefault] ASC
)
WHERE ([IsDefault]=(1))
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [FILE]
GO

ALTER TABLE [file].[ItemResourceFile]  WITH CHECK ADD  CONSTRAINT [FK_ItemResourceFile_Item] FOREIGN KEY([Item_ID])
REFERENCES [file].[Item] ([ID])
GO

ALTER TABLE [file].[ItemResourceFile] CHECK CONSTRAINT [FK_ItemResourceFile_Item]
GO

ALTER TABLE [file].[ItemResourceFile]  WITH CHECK ADD  CONSTRAINT [FK_ItemResourceFile_ResourceFile] FOREIGN KEY([ResourceFile_ID])
REFERENCES [file].[ResourceFile] ([ID])
GO

ALTER TABLE [file].[ItemResourceFile] CHECK CONSTRAINT [FK_ItemResourceFile_ResourceFile]
GO

ALTER TABLE [file].[ItemResourceFile]  WITH CHECK ADD  CONSTRAINT [FK_ItemResourceFile_User] FOREIGN KEY([CreatorUser_ID])
REFERENCES [system].[User] ([ID])
GO

ALTER TABLE [file].[ItemResourceFile] CHECK CONSTRAINT [FK_ItemResourceFile_User]
GO

ALTER TABLE [file].[ItemResourceFile]  WITH CHECK ADD  CONSTRAINT [FK_ItemResourceFile_User1] FOREIGN KEY([LastModifierUser_ID])
REFERENCES [system].[User] ([ID])
GO

ALTER TABLE [file].[ItemResourceFile] CHECK CONSTRAINT [FK_ItemResourceFile_User1]
GO

SP

ALTER PROCEDURE [file].[usp_iudItemResourceFile]
    @p_ItemID INT
    , @p_ID INT = NULL OUTPUT
    , @p_IsDefault BIT = NULL
    , @p_Description NVARCHAR ( MAX ) = NULL

    --, @p_RelPath NVARCHAR ( 2000 ) = NULL
    , @p_Name NVARCHAR ( 250 ) = NULL
    , @p_sequenceNumberID INT = NULL
    , @p_Type TINYINT = NULL
    , @p_Size INT = NULL
    , @p_Status TINYINT = NULL
    , @p_DoerTicket VARCHAR ( 200 ) = NULL
AS
BEGIN
    SET NOCOUNT ON;
    SET XACT_ABORT ON;

    DECLARE @doerUserID INT
            , @doerCompanyID INT
    EXEC system.usp_validateAuthenticationTicket @p_Ticket = @p_DoerTicket
                                                , @p_UserID = @doerUserID OUTPUT
                                                , @p_CompanyID = @doerCompanyID OUTPUT


    BEGIN TRANSACTION

    IF ( @p_ID < 0 )
    BEGIN
        PRINT 'TBD'
    END

    DECLARE @res INT
    EXEC @res = [file].usp_iudResourceFile @p_ID = @p_ID OUTPUT
                                    --, @p_RelPath = @p_RelPath
                                    , @p_Name = @p_Name
                                    , @p_Type = @p_Type
                                    , @p_Size = @p_Size
                                    , @p_Status = @p_Status
                                    , @p_DoerTicket = @p_DoerTicket

    IF ( ( @@ERROR <> 0 ) OR ( @res <> 0 ) )    
    BEGIN
        IF ( @@TRANCOUNT > 0 ) ROLLBACK TRANSACTION
        RETURN 1050
    END

    IF ( ( @p_ID > 0 ) AND ( @p_IsDefault = 1 ) )
    BEGIN
        UPDATE [file].ItemResourceFile SET
            IsDefault = 0
        WHERE Item_ID = @p_ItemID

        IF ( @@ERROR <> 0 ) 
        BEGIN
            IF ( @@TRANCOUNT > 0 ) ROLLBACK TRANSACTION
            RETURN 1053
        END
    END

    MERGE INTO [file].ItemResourceFile AS target
    USING ( SELECT @p_ItemID
                    , @p_ID
                    , @p_IsDefault
                    , @p_Description
                    , @p_Status
                    , @p_sequenceNumberID
                    , @doerUserID
                    , @doerCompanyID ) AS source ( ItemID, ResourceFileID, IsDefault, Description, Status, sequenceID, DoerUserID, DoerCompanyID )
        ON ( target.Item_ID = source.ItemID )
            AND ( target.ResourceFile_ID = source.ResourceFileID )
        WHEN MATCHED THEN
            UPDATE SET 
                target.Description = NULLIF ( ISNULL ( source.Description, target.Description ), N'' )
                , target.IsDefault = ISNULL ( source.IsDefault, target.IsDefault )
                , target.Status = ISNULL ( source.Status, target.Status )
                , target.sequenceID = source.sequenceID
                , target.LastModifierUser_ID = source.DoerUserID
                , target.DateTimeModified = GETUTCDATE ( )
        WHEN NOT MATCHED BY TARGET AND source.ResourceFileID > 0 THEN
            INSERT ( Item_ID
                    , ResourceFile_ID
                    , Description
                    , IsDefault
                    , Status
                    , sequenceID
                    , CreatorUser_ID
                    , LastModifierUser_ID )
                VALUES ( source.ItemID
                        , source.ResourceFileID
                        , NULLIF ( source.Description, N'' )
                        , ISNULL ( source.IsDefault, 0 )
                        , ISNULL ( source.Status, 0 ) --0: Active
                        , source.sequenceID
                        , source.DoerUserID
                        , source.DoerUserID
                        )
        WHEN NOT MATCHED BY SOURCE 
                AND target.Item_ID = @p_ItemID
                AND target.ResourceFile_ID = ABS ( @p_ID ) THEN
            DELETE;

    IF ( @@ROWCOUNT <> 1 )
    BEGIN
        IF ( @@TRANCOUNT > 0 ) ROLLBACK TRANSACTION
        RAISERROR ( 'DBException_ItemNotFound', 16, 1 )
        RETURN 1060
    END

    --IF ( @p_ID IS NULL )
    --  SET @p_ID = SCOPE_IDENTITY ( )

    COMMIT TRANSACTION

    RETURN 0
END

我该如何解决?

0 个答案:

没有答案