(UPDLOCK, ROWLOCK) verrouille toute la table même difficile seulement 1 ligne est sélectionnée

Dans notre application Java, nous utilisons une instruction SQL Server pour mettre en pause certains process.

C'est l'instruction SQL:

SELECT * FROM MESSAGES WITH (UPDLOCK, ROWLOCK) WHERE MESSAGES.INTERNAL_ID IN ('6f53448f-1c47-4a58-8839-e126e81130f0'); 

Les UUID dans la clause IN changent bien sûr d'une exécution à l'autre.

C'est le code Java que nous utilisons pour le locking:

 entityManager.createNativeQuery(sqlSsortingng).getResultList() 

L'instruction SQL ci-dessus ne renvoie qu'une seule ligne. Malheureusement, il semble que toute la table est verrouillée. Le résultat est que tous les process sont verrouillés même si aucun ou seulement certains doivent être bloqués.

Pourquoi la table entière est-elle verrouillée même si je spécifie UPDLOCK ?


Information additionnelle:

  • MESSAGES.INTERNAL_ID est NVARCHAR(255) qui n'est pas Nullable. Sinon, il n'y a pas de contrainte sur la colonne.
  • Le niveau d'isolation est READ_COMMITTED .

C'est parce que votre MESSAGES.INTERNAL_ID n'est pas une key. Une fois la ligne verrouillée, vous ne pouvez plus la lire et vérifier sa valeur. Essayez de créer une key primaire sur cette colonne.

Si c'est impossible, créez INDEX dessus et réécrivez votre requête:

 SELECT MESSAGES.INTERNAL_ID FROM MESSAGES WITH (UPDLOCK, ROWLOCK) WHERE MESSAGES.INTERNAL_ID IN ('6f53448f-1c47-4a58-8839-e126e81130f0'); 

MSDN dit:

Les indications de locking ROWLOCK, UPDLOCK et XLOCK qui acquièrent des verrous au niveau de la ligne peuvent placer des verrous sur les keys d'index plutôt que sur les lignes de données réelles. Par exemple, si une table a un index non cluster et qu'une instruction SELECT utilisant un indicateur de locking est traitée par un index de couverture, un verrou est acquis sur la key d'index dans l'index de couverture plutôt que sur la ligne de données dans la table de base.