如何进行并发存储过程调用而没有死锁?

时间:2019-01-13 05:28:19

标签: sql-server stored-procedures deadlock

我有一个存储过程,该存储过程创建一个临时表,将数据插入其中并进行一些操作。完成后,将删除临时表。我正在TRANSACTION中运行它。但是尽管如此,当我运行存储过程的多个实例时,它导致了死锁,并且存储过程现在没有响应。有没有办法来解决这个问题?该存储过程用于使用JSON文本创建通用后端表。

CREATE OR ALTER PROCEDURE dbo.INSERT_PROCESSING
    @TableName NVARCHAR(128),
    @InsertStatement NVARCHAR(1000) 
AS 
BEGIN
    DECLARE
        @tableSK INTEGER,
        @attribute_list NVARCHAR(1000),
        @json_txt NVARCHAR(1000),
        @json_txt_final NVARCHAR(1000),
        @K_SK_SysKey NVARCHAR(1000),
        @tmp_create_stmt NVARCHAR(1000),
        @tmp_table_ddl1 NVARCHAR(1000),
        @tmp_table_ddl NVARCHAR(1000),
        @tmp_table_drop NVARCHAR(1000),
        @modified_insert_stmt NVARCHAR(1000)

    PRINT 'Values passed are' 
    PRINT '1. TableName: ' + @TableName
    PRINT '2. InsertStatement: ' + @InsertStatement

    --1. Derive TableSK
    SET  @tableSK = ( SELECT DISTINCT SK
           FROM [SS_PRODUCTS].[dbo].[METADATA_TABLE] WHERE RTRIM(LTRIM(TableName)) = LTRIM(RTRIM(SUBSTRING(@TableName, 2, 128)))); 

    --2. Parse out the atributes from the INSERT Statement
    SELECT @attribute_list = SUBSTRING(@InsertStatement, CHARINDEX('(', @InsertStatement) , LEN(@InsertStatement));
    PRINT 'Value of @attribute_list' + @attribute_list;
    SET @K_SK_SysKey = REPLACE(SUBSTRING(@attribute_list, 3 , CHARINDEX(',', @attribute_list)-3 ), '''', ''); 
    PRINT 'Value of @K_SK_SysKey ' + @K_SK_SysKey;
    SET @modified_insert_stmt = 'INSERT INTO [dbo].TMP_TABLE VALUES ' + @attribute_list;

    --3. Create a Tmp table with the metadata available

    SET @tmp_create_stmt = STUFF((SELECT ' ,' + UPPER(TColumnName) + ' ' + TColumnDataType
            FROM [dbo].[METADATA_TABLE] WHERE SK=@tableSK ORDER BY TColumnOrder
            FOR XML PATH('')  ) ,1,1,'') ;

    SET @tmp_table_ddl1 = RIGHT(@tmp_create_stmt, LEN(@tmp_create_stmt) -1);
    SET @tmp_table_ddl = 'CREATE TABLE [dbo].TMP_TABLE'   +  ' ( ' + @tmp_table_ddl1 + ' );'
    PRINT 'TABLE DDL is ' + @tmp_table_ddl;

    SET @tmp_table_drop = 'DROP TABLE IF EXISTS [dbo].TMP_TABLE' ;

    BEGIN TRANSACTION 
    -- Try catch to handle exceptions
    BEGIN TRY 
        EXEC (@tmp_table_drop);
        PRINT 'TMP Table dropped'
    END TRY 
    BEGIN CATCH
        PRINT 'Table drop was not successful' ;
        RETURN 10;
    END CATCH

    BEGIN TRY
     EXEC (@tmp_table_ddl);
     PRINT 'TMP Table re-created'

    END TRY
    BEGIN CATCH 
        PRINT 'Table creation was not successful' ;
        RETURN 20;  
    END CATCH

     BEGIN TRY
        EXEC (@modified_insert_stmt);
        PRINT ' Insert to TMP Table successful'

     END TRY
    BEGIN CATCH 
        PRINT 'Table insert was not successful';
        RETURN 30;  
    END CATCH

        --CREATE JSON
        SET @json_txt = (SELECT * FROM dbo.TMP_TABLE FOR JSON AUTO, INCLUDE_NULL_VALUES );
        SET @json_txt_final = REPLACE(REPLACE( @json_txt, '[', ''), ']', '');

        PRINT 'Final Json txt is ' + @json_txt_final; 

        -- Insert into the target table
        INSERT INTO [dbo].[CONSOLIDATED_TABLE] ( SK, K_SK_SysKey, ACCESS_DATA_JSON )
        VALUES (@tableSK, @K_SK_SysKey, @json_txt_final );

    IF @@TRANCOUNT > 0
    BEGIN
        COMMIT TRANSACTION
        PRINT '*** Data inserted successfully***'
    END
END;

1 个答案:

答案 0 :(得分:0)

您的临时表是否应使用井号'#'进行限定。 #temp表应包含在该会话中,并且不得与其他会话冲突:

CREATE TABLE [dbo].#TMP_TABLE