首页 > 解决方案 > 很多查询被暂停。我应该怎么办?

问题描述

我正在处理大约 2000 人使用的应用程序。日常用户同时插入大约 300 行/用户(大约上午 7 点到上午 11 点)。我使用仅包含插入语句的存储过程来处理它,但我使用它begin tran来防止主键重复。

当前挂起的事务经常发生,所以我的存储过程大约需要 1-2 分钟才能完成,这导致我们的用户等待很长时间才能插入每个数据。我已经检查过:

  1. 读取磁盘速度正常:600mb/s 写入 744mb/s。

  2. 10 个内核的处理器使用率在 20 - 40 % 之间。

  3. 内存使用只有6gb,我用了12gb的内存。

  4. sys.dm_exec_requestssp_who2和进行检查sys.dm_os_waiting_tasks

    数字 3 的结果是我发现我的存储过程相互挂起(相同的存储过程不同的执行程序)

这是我的存储过程(对不起,命名,因为它是我公司的机密):


ALTER PROC [dbo].[SP_DESTIONATION_TABLE_INSERT]
    {params}
WITH RECOMPILE
AS
BEGIN   
    BEGIN TRAN InsertT
    
    DECLARE @ERRORNMBR INT
    
    SET @ERRORNMBR = 0

    IF @T = ''
    BEGIN   
        -------------------------------------------------
        DECLARE @TCID VARCHAR(15)

        SELECT @TCID = ID
        FROM DESTIONATION_TABLE 
        WHERE   NIK = @NIK AND
                CUSTOMERID = @CUSTOMERID AND 
                    CUSTOMERTYPE = @CUSTOMERTYPE AND --edit NvA 20180111
                DATEDIFF(day,DATE,@DATE) = 0

        --IF THERE IS ALREADY A CALL IN SERVER
        IF @TCID IS NOT NULL
        BEGIN
            IF @INTERFACE <> 'WEB' BEGIN
                --GET EXISTING CALL ID
                SET @ID = @TCID

                BEGIN TRAN UBAH
                UPDATE DESTIONATION_TABLE
                SET 
                    columns=value
                WHERE ID = @ID
                    AND employeeid = @employeeid
                    AND CUSTOMERID = @CUSTOMERID 

                SET @ERRORNMBR = @ERRORNMBR + @@ERROR
                IF @ERRORNMBR = 0
                BEGIN
                    COMMIT TRAN UBAH
                    SELECT 
                        columns
                    FROM DESTIONATION_TABLE WHERE ID = @ID
                END
                ELSE
                BEGIN
                    ROLLBACK TRAN UBAH
                END 
            END
            COMMIT TRAN InsertT
            RETURN
        END
        --------------------------------------------------

        -- CHECK @DEVICECONTROLID
        IF @DEVICECONTROLID IS NOT NULL
            AND @INTERFACE <> 'WEB' 
            AND EXISTS(SELECT 1 FROM DESTIONATION_TABLE WHERE DEVICECONTROLID = @DEVICECONTROLID)
        BEGIN
            IF NOT EXISTS(SELECT 1 FROM DESTIONATION_TABLE_TEMP WHERE DEVICECONTROLID = @DEVICECONTROLID)
            BEGIN
                INSERT INTO DESTIONATION_TABLE_TEMP
                       (COLUMNS)
                 VALUES
                       (VALUES)
            END
                        
            SELECT * FROM DESTIONATION_TABLE WHERE _DEVICECONTROLID = @_DEVICECONTROLID
        END
        ELSE
        BEGIN   
            some logic to make primary key formula{string+date+employeeid+increment}
        END
    END
    ELSE
    BEGIN
        BEGIN TRAN UBAH

        IF @PARAMS = 'WEB' 
        BEGIN
            UPDATE DESTIONATION_TABLE
            SET 
                COLUMNS = PARAMS
            WHERE ID = @ID
        END
        ELSE IF PARAMS = 'MOBILE'
        BEGIN
            UPDATE DESTIONATION_TABLE
            SET 
                COLUMNS = PARAMS
            WHERE ID = ID
        END

        SET @ERRORNMBR = @ERRORNMBR + @@ERROR
        
        IF @ERRORNMBR = 0
        BEGIN
            COMMIT TRAN UBAH
            SELECT 
                COLUMNS
             FROM DESTIONATION_TABLE WHERE ID = ID
        END
        ELSE
        BEGIN
            ROLLBACK TRAN UBAH
        END
    END

    COMMIT TRAN InsertT


END

在此处输入图像描述

我需要一个建议,接下来我应该检查什么以了解我的服务器出了什么问题。

begin tran这里的问题吗?

标签: sqlsql-serverdeadlockdatabase-deadlocks

解决方案


我不是专家,但谷歌搜索“BEGIN TRAN”似乎表明它“锁定表,直到事务通过“COMMIT TRAN”提交......这意味着它是一个阻塞过程。所以如果你是当所有这些插入尝试执行时,表被锁定,其中一些显然不会成功。

https://www.mssqltips.com/sqlservertutorial/3305/what-does-begin-tran-rollback-tran-and-commit-tran-mean/

我建议在它自己的线程上建立一个工作队列来监听 INSERTS/UPDATES。然后队列可以在空闲时清空到数据库中。


推荐阅读