zoukankan      html  css  js  c++  java
  • DeadLock

    1. What causes the deadlock?

    I take “Generate SubAccountId” as example.

    <1> At last I find “ A TRIGGER tg_s_SAid_Add ON s_SAid FOR INSERT delay to commit transaction” leads to deadlock

    <2>Detailed script about tg_s_SAid_Add as following

    --use SeedData

    --exec sp_helptext tg_s_SAid_Add

    CREATE TRIGGER tg_s_SAid_Add ON s_SAid 

    FOR INSERT     

    AS     

     DELETE FROM dbo.s_SAid

    1. How to track this trigger

    <1> Open two SQL Server Query to execute the following script at the same time.

    --SELECT GETDATE()

    --WAITFOR TIME '20:21:20'

    USE SeedData

    DECLARE @count INT

    SET @count=1

    WHILE(@count<1000)

    BEGIN

        SET @count=@count+1

        BEGIN TRY

    ------------------------------------------Main Process--------------------------------------------------

           DECLARE  @p_Type        CHAR(2)

           DECLARE  @p_CountryId   CHAR(3)

           DECLARE  @r_SecId       CHAR(10)

           SET  @p_Type='SA'     

           SET  @p_CountryId='USA'

            -- Variable declaration

              -- Always set error handling variables first

              DECLARE @l_Err      INTEGER,

                     @l_Msg      NVARCHAR(100),

                     @l_Id       NVARCHAR(15),

                     @l_ProcName VARCHAR(30),

                     @l_ProcDB   VARCHAR(30)

              DECLARE @l_TableName   CHAR(6),

                     @l_Cmd         NVARCHAR(100),

                     @l_OldId       INTEGER,

                     @l_NewId       VARCHAR(5)

              SET NOCOUNT ON

              -- Initialize error handle-related constants

              SET @l_Id       = ISNULL(@p_Type + @p_CountryId,'')

              SET @l_ProcName = OBJECT_NAME (@@PROCID)

              SET @l_ProcDB   = DB_NAME()

              SET @p_Type      = RTRIM(LTRIM(@p_Type))

              SET @p_CountryId = RTRIM(LTRIM(@p_CountryId))

              SET @r_SecId = NULL

              IF @p_Type NOT IN ('F0', 'FO', 'FC', 'FE', 'FM', 'FV', 'FS', 'FX', 'E0', 'VP', 'VA', 'B0', 'C0',

                               'BP', 'BM', 'XI', 'SA', 'SC', 'SP', 'CF', 'FH', 'ST','FA')

              BEGIN

                 SET @l_Err = 50001

                 SET @l_Msg = 'Invalid input: p_Type.'

                 GOTO OnError

              END

              IF LEN(@p_CountryId) <> 3

              BEGIN

                 SET @l_Err = 50001

                 SET @l_Msg = 'Invalid input: p_CountryId.'

                 GOTO OnError

              END

              IF @p_CountryId = '---'

              BEGIN

                 SET @p_CountryId = '000'

              END

              SELECT @l_TableName = 's_' + @p_Type + 'id'

              BEGIN TRANSACTION

                 SET @l_Cmd = N'INSERT INTO '+@l_TableName+' DEFAULT VALUES'

                 EXECUTE sp_executesql @l_Cmd

                 SELECT @l_OldId = @@IDENTITY,

                       @l_Err = @@ERROR

                 IF @l_Err <> 0

                 BEGIN

                   ROLLBACK TRANSACTION

                   SET @l_Msg = 'Insert on ' + @l_TableName + ' failed.'

                   GOTO OnError

                 END

                 IF @l_OldId > 0 AND @l_OldId <= POWER(36,4)-1

                 BEGIN

                   SET @l_NewId = ResourceData.dbo.fn_chgDecIntToNBaseInt(36, @l_OldId)

                   SET @l_Err = @@ERROR

                   IF @l_Err <> 0

                   BEGIN

                      ROLLBACK TRANSACTION

                      SET @l_Msg = 'Call on fn_chgDecIntToNBaseInt failed.'

                      GOTO OnError

                   END

                   IF @l_NewId = NULL

                   BEGIN

                      ROLLBACK TRANSACTION

                      SET @l_Err = 50002

                      SET @l_Msg = 'Invalid Id output from fn_chgDecIntToNBaseInt.'

                      GOTO OnError

                   END

                   SELECT @l_NewId = RIGHT('00000'+@l_NewId,5)

                   SELECT @r_SecId = @p_Type + @p_CountryId + @l_NewId

                 END

                 ELSE

                 BEGIN

                   ROLLBACK TRANSACTION

                   SET @l_Err = 50002

                   SET @l_Msg = 'Invalid Id output from insert on ' + @l_TableName

                   GOTO OnError

                 END

              COMMIT TRANSACTION

              --RETURN @@ERROR

              -- Error handling section

              OnError:

                 -- Store error and raise error

                 --EXECUTE sp_LogError @l_Err, @l_Msg, @l_Id, @l_ProcName, @l_ProcDB

                 --RAISERROR(@l_Msg, 18,1)

                 --RETURN @l_Err

    ---------------------------------------------------Main Process------------------------------------------------------

        END TRY

        BEGIN CATCH

            ROLLBACK TRANSACTION

           DECLARE @ErrorMessage VARCHAR(8000);

           SELECT  @ErrorMessage = 'ErrorMessage: '+ISNULL(CAST(ERROR_MESSAGE() AS VARCHAR(500)),'-')+CHAR(10)+

                                    'ERROR_SEVERITY: '+ISNULL(CAST(ERROR_SEVERITY()AS VARCHAR(500)),'-')+CHAR(10)+

                                    'ERROR_NUMBER: '+ISNULL(CAST(ERROR_NUMBER()AS VARCHAR(500)),'-')+CHAR(10)+

                                    'ERROR_STATE: '+ISNULL(CAST(ERROR_STATE()AS VARCHAR(500)),'-')+CHAR(10)+

                                    'ERROR_PROCEDURE: '+ISNULL(CAST(ERROR_PROCEDURE()AS VARCHAR(500)),'-')+CHAR(10)+

                                    'ERROR_LINE: '+ISNULL(CAST(ERROR_LINE()AS VARCHAR(500)),'-')

           --if deadlock happened ,print the detailed error message

           IF ERROR_NUMBER()=1205

           BEGIN

             PRINT @ErrorMessage

             BREAK;

           END                            

        END CATCH

    END

    <2> The print error message as following

    ErrorMessage: Transaction (Process ID 51) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

    ERROR_SEVERITY: 13

    ERROR_NUMBER: 1205

    ERROR_STATE: 45

    ERROR_PROCEDURE: tg_s_SAid_Add

    ERROR_LINE: 4

    <3> We can know code line 4 of trigger “tg_s_SAid_Add”  as the red font leads to the deadlock cregarding the error message 

    CREATE TRIGGER tg_s_SAid_Add ON s_SAid 

    FOR INSERT     

    AS     

     DELETE FROM dbo.s_SAid

    <4>we can use a simple example  instead of trigger “tg_s_SAid_Add”  as following to do a text

    1. Create a text table

    CREATE TABLE IdText(

                   [Id] [int] IDENTITY(1,1) NOT NULL)

    1. b. Open two SQL Server Query to execute the following script at the same time then the same deadlock happened again.

    Begin Tran

    INSERT INTO IdTable DEFAULT VALUES

       WaitFor Delay '00:01:00';

       DELETE FROM IdTable

    Rollback Tran;

    1. A solution to avoid deadlock for above simple example is to seperated the big transaction as following  and

         open two SQL Server Query to execute the following script at the same time then the deadlock will never happened

             INSERT INTO IdTable DEFAULT VALUES

            DELETE FROM IdTable

    1. The solution for u_getCode

    <1>drop  TRIGGER of “tg_s_SAid_Add” first.

    <2>Execute delete sql script after transaction commit as Yellow highlight

    <3>After drop the TRIGGER then open two SQL Server Query to execute the following script

    --SELECT GETDATE()

    --WAITFOR TIME '20:21:20'

    USE SeedData

    DECLARE @count INT

    SET @count=1

    WHILE(@count<1000)

    BEGIN

        SET @count=@count+1

        BEGIN TRY

    ------------------------------------------Main Process--------------------------------------------------

           DECLARE  @p_Type        CHAR(2)

           DECLARE  @p_CountryId   CHAR(3)

           DECLARE  @r_SecId       CHAR(10)

           SET  @p_Type='SA'     

           SET  @p_CountryId='USA'

            -- Variable declaration

              -- Always set error handling variables first

              DECLARE @l_Err      INTEGER,

                     @l_Msg      NVARCHAR(100),

                     @l_Id       NVARCHAR(15),

                     @l_ProcName VARCHAR(30),

                     @l_ProcDB   VARCHAR(30)

              DECLARE @l_TableName   CHAR(6),

                     @l_Cmd         NVARCHAR(100),

                     @l_OldId       INTEGER,

                     @l_NewId       VARCHAR(5)

              SET NOCOUNT ON

              -- Initialize error handle-related constants

              SET @l_Id       = ISNULL(@p_Type + @p_CountryId,'')

              SET @l_ProcName = OBJECT_NAME (@@PROCID)

              SET @l_ProcDB   = DB_NAME()

              SET @p_Type      = RTRIM(LTRIM(@p_Type))

              SET @p_CountryId = RTRIM(LTRIM(@p_CountryId))

              SET @r_SecId = NULL

              IF @p_Type NOT IN ('F0', 'FO', 'FC', 'FE', 'FM', 'FV', 'FS', 'FX', 'E0', 'VP', 'VA', 'B0', 'C0',

                               'BP', 'BM', 'XI', 'SA', 'SC', 'SP', 'CF', 'FH', 'ST','FA')

              BEGIN

                 SET @l_Err = 50001

                 SET @l_Msg = 'Invalid input: p_Type.'

                 GOTO OnError

              END

              IF LEN(@p_CountryId) <> 3

              BEGIN

                 SET @l_Err = 50001

                 SET @l_Msg = 'Invalid input: p_CountryId.'

                 GOTO OnError

              END

              IF @p_CountryId = '---'

              BEGIN

                 SET @p_CountryId = '000'

              END

              SELECT @l_TableName = 's_' + @p_Type + 'id'

              BEGIN TRANSACTION

                 SET @l_Cmd = N'INSERT INTO '+@l_TableName+' DEFAULT VALUES'

                 EXECUTE sp_executesql @l_Cmd

                 SELECT @l_OldId = @@IDENTITY,

                       @l_Err = @@ERROR

                 IF @l_Err <> 0

                 BEGIN

                   ROLLBACK TRANSACTION

                   SET @l_Msg = 'Insert on ' + @l_TableName + ' failed.'

                   GOTO OnError

                 END

                 IF @l_OldId > 0 AND @l_OldId <= POWER(36,4)-1

                 BEGIN

                   SET @l_NewId = ResourceData.dbo.fn_chgDecIntToNBaseInt(36, @l_OldId)

                   SET @l_Err = @@ERROR

                   IF @l_Err <> 0

                   BEGIN

                      ROLLBACK TRANSACTION

                      SET @l_Msg = 'Call on fn_chgDecIntToNBaseInt failed.'

                      GOTO OnError

                   END

                   IF @l_NewId = NULL

                   BEGIN

                      ROLLBACK TRANSACTION

                      SET @l_Err = 50002

                      SET @l_Msg = 'Invalid Id output from fn_chgDecIntToNBaseInt.'

                      GOTO OnError

                   END

                   SELECT @l_NewId = RIGHT('00000'+@l_NewId,5)

                   SELECT @r_SecId = @p_Type + @p_CountryId + @l_NewId

                 END

                 ELSE

                 BEGIN

                   ROLLBACK TRANSACTION

                   SET @l_Err = 50002

                   SET @l_Msg = 'Invalid Id output from insert on ' + @l_TableName

                   GOTO OnError

                 END

              COMMIT TRANSACTION

               --here ,execute delete sql script

               SET @l_Cmd = N'DELETE FROM  '+@l_TableName

               EXECUTE sp_executesql @l_Cmd

              --RETURN @@ERROR

              -- Error handling section

              OnError:

                 -- Store error and raise error

                 --EXECUTE sp_LogError @l_Err, @l_Msg, @l_Id, @l_ProcName, @l_ProcDB

                 --RAISERROR(@l_Msg, 18,1)

                 --RETURN @l_Err

    ---------------------------------------------------Main Process------------------------------------------------------

        END TRY

        BEGIN CATCH

            ROLLBACK TRANSACTION

           DECLARE @ErrorMessage VARCHAR(8000);

           SELECT  @ErrorMessage = 'ErrorMessage: '+ISNULL(CAST(ERROR_MESSAGE() AS VARCHAR(500)),'-')+CHAR(10)+

                                    'ERROR_SEVERITY: '+ISNULL(CAST(ERROR_SEVERITY()AS VARCHAR(500)),'-')+CHAR(10)+

                                    'ERROR_NUMBER: '+ISNULL(CAST(ERROR_NUMBER()AS VARCHAR(500)),'-')+CHAR(10)+

                                    'ERROR_STATE: '+ISNULL(CAST(ERROR_STATE()AS VARCHAR(500)),'-')+CHAR(10)+

                                    'ERROR_PROCEDURE: '+ISNULL(CAST(ERROR_PROCEDURE()AS VARCHAR(500)),'-')+CHAR(10)+

                                    'ERROR_LINE: '+ISNULL(CAST(ERROR_LINE()AS VARCHAR(500)),'-')

           --if deadlock happened ,print the detailed error message

           IF ERROR_NUMBER()=1205

           BEGIN

             PRINT @ErrorMessage

             BREAK;

           END                            

        END CATCH

    END

    <4>Text more times find everything is ok

  • 相关阅读:
    Linux大文件传输(转)
    SSH登录很慢问题的解决
    tcp-ip-状态详解(转)
    shell下root用户切换其他用户运行程序
    Linux进程内存分析pmap命令(转)
    svn在linux下的使用(转)
    双重检查锁定及单例模式(转)
    深入分析Volatile的实现原理(转)
    JMM & synchronized概述(转)
    性能测试工具Locust
  • 原文地址:https://www.cnblogs.com/flysun0311/p/1887813.html
Copyright © 2011-2022 走看看