许多更新都会出现死锁错误

时间:2017-08-07 18:31:39

标签: sql-server node.js sequelize.js

使用node.js + sequelize.js + mssql

我每5秒钟从3个线程做很多更新〜30(一个表)。设备轮询。

获取

  

SequelizeDatabaseError:事务(进程ID 57)已死锁   用另一个进程锁定资源并被选为   僵局受害者。重新运行该交易。

sequelize generate sql

sql: 

SET IDENTITY_INSERT [DeviceCurrentData] ON;

MERGE INTO [DeviceCurrentData] WITH (HOLDLOCK) AS [DeviceCurrentData_target]
USING (
    VALUES (
        9,
        N\ '28.300000\',
        \ '2017-08-07 15:26:28.000\',
        12
        )
    ) AS [DeviceCurrentData_source]([Id], [Value], [DateStamp], [DevParamId])
    ON [DeviceCurrentData_target].[Id] = [DeviceCurrentData_source].[Id]
WHEN MATCHED
    THEN
        UPDATE
        SET [DeviceCurrentData_target].[Value] = N\ '28.300000\',
            [DeviceCurrentData_target].[DateStamp] = \ '2017-08-07 15:26:28.000\',
            [DeviceCurrentData_target].[DevParamId] = 12
WHEN NOT MATCHED
    THEN
        INSERT (
            [Id],
            [Value],
            [DateStamp],
            [DevParamId]
            )
        VALUES (
            9,
            N\ '28.300000\',
            \ '2017-08-07 15:26:28.000\',
            12
            )
OUTPUT $ACTION,
    INSERTED.*;

SET IDENTITY_INSERT [DeviceCurrentData] OFF;

'

1 个答案:

答案 0 :(得分:0)

HOLDLOCK是一个表级锁。一旦发出,就阻止任何其他事务修改表内容,直到HOLDLOCK事务完成。 MERGE对并发性不利,因为它有多个阶段,其他事务可能会卡住..

对于高并发性,您应该使用upsert。 (尝试更新,如果输出为null,请执行插入操作)。

此外,使用完整的聚簇索引键,更新最好一次针对一行。如果您尝试更新多行或索引未涵盖过滤器,则可能会升级为更大的锁定并导致死锁。

缓解死锁是一个复杂的话题。祝你好运。