使用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;
'
答案 0 :(得分:0)
HOLDLOCK是一个表级锁。一旦发出,就阻止任何其他事务修改表内容,直到HOLDLOCK事务完成。 MERGE对并发性不利,因为它有多个阶段,其他事务可能会卡住..
对于高并发性,您应该使用upsert。 (尝试更新,如果输出为null,请执行插入操作)。
此外,使用完整的聚簇索引键,更新最好一次针对一行。如果您尝试更新多行或索引未涵盖过滤器,则可能会升级为更大的锁定并导致死锁。
缓解死锁是一个复杂的话题。祝你好运。