为什么要使用MERGE插入多个记录的SQL Server升级?

问题描述 投票:0回答:1

我在Microsoft SQL Server 2017 Standard Edition的存储过程中使用MERGE语句实现了upsert。

问题是,在对存储过程进行并发调用时,我得到了多个插入。我可以使用具有许多并发线程的JMeter重现该行为。 JMeter命中了一个Java Web应用程序,该应用程序使用JDBC调用存储过程。删除所有行并运行JMeter后,它通常仅创建1行,但有时会创建2个或更多行。我想我已经看到它最多创建6行。

我以为使用MERGE,这是不可能的。这个问题的答案都说交易是不必要的:Is neccessary to encapsulate a single merge statement (with insert, delete and update) in a transaction?

[基本上,我希望表存储每天的最大大小(LQ_SIZE)值,以及最大大小发生的时间(LQ_TIMESTAMP)。我在upsert中做两件不寻常的事情。 1.我要匹配转换为日期的时间戳,所以我将忽略该时间插入或更新该行。 2.我的WHEN MATCHED子句具有AND条件,因此仅当新大小大于当前大小时才更新行。

这是我的表和带有MERGE语句的存储过程:

CREATE TABLE LOG_QUEUE_SIZE (
    LQ_APP_ID SMALLINT NOT NULL,
    LQ_TIMESTAMP DATETIME2,
    LQ_SIZE INT
);
GO

CREATE PROCEDURE LOG_QUEUE_SIZE (
    @P_TIMESTAMP    DATETIME2,
    @P_APP_ID       SMALLINT,
    @P_QUEUE_SIZE   INT
)
AS 
BEGIN
    -- INSERT or UPDATE the max LQ_QUEUE_SIZE for today in the LOG_QUEUE_SIZE table
    MERGE 
        LOG_QUEUE_SIZE target
        USING 
            (SELECT @P_APP_ID NEW_APP_ID, @P_TIMESTAMP NEW_TIMESTAMP, @P_QUEUE_SIZE NEW_SIZE) source
        ON 
            LQ_APP_ID=NEW_APP_ID 
            AND CAST(NEW_TIMESTAMP AS DATE) = CAST(LQ_TIMESTAMP AS DATE) -- Truncate the timestamp to the day
    WHEN MATCHED AND NEW_SIZE > LQ_SIZE THEN -- Only update if we have a new max size for today
        UPDATE 
        SET 
            LQ_TIMESTAMP = NEW_TIMESTAMP, 
            LQ_SIZE = NEW_SIZE
    WHEN NOT MATCHED BY TARGET THEN -- Otherwise insert the new size
        INSERT 
            (LQ_APP_ID, 
            LQ_TIMESTAMP, 
            LQ_SIZE)
        VALUES
            (NEW_APP_ID, 
            NEW_TIMESTAMP, 
            NEW_SIZE);
END

似乎使用事务处理(在合并处带有BEGIN TRAN...COMMIT,可以防止该问题,但是性能很糟糕。

如果MERGE是原子的,为什么我会得到多个插入物?我该如何预防?

sql sql-server tsql sql-server-2017
1个回答
1
投票

MERGE,导致多个SQL语句,这意味着它可能导致可能的并发冲突。您应该实现锁定:

MERGE dbo.TableName WITH (HOLDLOCK) AS target
USING ... AS source ...;

https://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/

© www.soinside.com 2019 - 2024. All rights reserved.