必威体育Betway必威体育官网
当前位置:首页 > IT技术

DeadLock

时间:2019-10-01 09:16:13来源:IT技术作者:seo实验室小编阅读:59次「手机版」
 

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

转载于:https://www.cnblogs.com/flysun0311/archive/2010/11/25/1887813.html

相关阅读

解决 APPARENT DEADLOCK!!!

解决 APPARENT DEADLOCK!!! Creating emergency threads for unassigned pending tasks报错信息:报错信息: APPARENT DEADLOCK!!! C

SQL Server上的一个奇怪的Deadlock及其分析方法

原文: https://blogs.msdn.microsoft.com/apgcdsd/2012/02/27/sql-serverdeadlock/最近遇到了一个看上去很奇怪,分析起来很有意思

分享到:

栏目导航

推荐阅读

热门阅读