2017-08-07 1 views
0

Utilisez Node.js + sequelize.js + MSSQLDe nombreuses mises à jour de blocage se erreur

Je fais beaucoup de mises à jour ~ 30 (une table) à partir de 3 fils toutes les 5 secondes. L'interrogation du périphérique.

Get

SequelizeDatabaseError: Transaction (Process ID 57) was deadlocked on lock resources with another process and has been chosen as the deadlock victim. Rerun the transaction.

sequelize générer 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

[Cette réponse précédente] (https://stackoverflow.com/questions/7843733/confused-about-updlock-holdlock) peut vous aider. Votre utilisation de 'HOLDLOCK' bloquerait à la fois' INSERT' et 'UPDATE', alors que' UPDLOCK' bloquerait seulement 'UPDATE'. Vous devriez tracer ce spid et trouver si c'était un 'INSERT' ou' UPDATE' qui a échoué. – Phoenix

+0

J'écris 'Model.update (item, {Id: item.Id})', mais sequelize.js geneterate 'HOLDLOCK'. J'ai écrit 'Model.upsert', également obtenir une erreur de blocage –

Répondre

0

HOLDLOCK est un verrou de niveau de la table. Une fois qu'il a été émis, toutes les autres transactions sont empêchées de modifier le contenu de la table jusqu'à la fin de la transaction HOLDLOCK. MERGE n'est pas bon pour la simultanéité car il comporte plusieurs phases dans lesquelles d'autres transactions peuvent être bloquées.

Pour une simultanéité élevée, vous devriez probablement utiliser un upsert. (Essayez une mise à jour, si la sortie est nulle, faites une insertion).

De même, la mise à jour est mieux ciblée sur une seule ligne à la fois, en utilisant la clé d'index clusterisée complète. Si vous essayez de mettre à jour plusieurs lignes ou si votre filtre n'est pas couvert par l'index, il peut devenir un verrou plus grand et provoquer des blocages.

Atténuer les blocages est un sujet compliqué. Bonne chance.

+0

Model.upsert également obtenir une erreur de blocage. En-tête avec HOLDLOCK générer automatiquement, puis-je le changer? Lorsque je travaille avec C# et EntityFramework, je n'ai pas cette erreur –

+0

Oui, vous pouvez supprimer le verrou de maintien. Vous ne devriez pas avoir besoin d'ajouter un verrou pour cette transaction simple, en supposant que l'ID est votre champ clé primaire. Une autre option est une suppression/insertion. Plutôt que de mettre à jour l'enregistrement, supprimez-le puis insérez-le. –