Sqlserver
 sql >> Base de données >  >> RDS >> Sqlserver

Confus à propos de UPDLOCK, HOLDLOCK

Pourquoi UPDLOCK bloquerait-il les sélections ? La matrice de compatibilité des verrous indique clairement N pour le conflit S/U et U/S, comme dans Pas de conflit .

En ce qui concerne l'indice HOLDLOCK, la documentation indique :

HOLDLOCK :équivaut à SERIALIZABLE. Pour plus d'informations, consultez SERIALIZABLE plus loin dans cette rubrique.

...

SERIALIZABLE :... L'analyse est effectuée avec la même sémantique qu'une transaction s'exécutant au niveau d'isolement SERIALIZABLE...

et la rubrique Niveau d'isolation des transactions explique ce que signifie SERIALIZABLE :

Aucune autre transaction ne peut modifier les données qui ont été lues par la transaction en cours tant que la transaction en cours n'est pas terminée.

Les autres transactions ne peuvent pas insérer de nouvelles lignes avec des valeurs de clé qui tomberaient dans la plage de clés lues par les instructions de la transaction en cours jusqu'à ce que la transaction en cours soit terminée.

Par conséquent, le comportement que vous voyez est parfaitement expliqué par la documentation du produit :

  • UPDLOCK ne bloque pas les SELECT ni INSERT simultanés, mais bloque tout UPDATE ou DELETE des lignes sélectionnées par T1
  • HOLDLOCK signifie SERALIZABLE et autorise donc SELECTS, mais bloque UPDATE et DELETES des lignes sélectionnées par T1, également comme tout INSERT dans la plage sélectionnée par T1 (qui est la table entière, donc any insérer).
  • (UPDLOCK, HOLDLOCK) :votre expérience ne montre pas ce qui bloquerait en plus du cas ci-dessus, à savoir une autre transaction avec UPDLOCK dans T2 :
    SELECT * FROM dbo.Test WITH (UPDLOCK) WHERE ...
  • TABLOCKX pas besoin d'explications

La vraie question est qu'essayez-vous d'accomplir ? Jouer avec des indices de verrouillage sans une compréhension absolue à 110 % de la sémantique de verrouillage est source d'ennuis...

Après l'édition OP :

Je souhaite sélectionner des lignes dans une table et empêcher que les données de cette table ne soient modifiées pendant que je les traite.

Ensuite, vous devez utiliser l'un des niveaux d'isolation de transaction les plus élevés. REPEATABLE READ empêchera les données que vous lisez d'être modifiées. SERIALIZABLE empêchera les données que vous lisez d'être modifiées et nouvelles données d'être insérées. L'utilisation de niveaux d'isolation de transaction est la bonne approche, par opposition à l'utilisation d'indicateurs de requête. Kendra Little a une belle affiche expliquant les niveaux d'isolement.