Comprendre les verrous SQL Server sur les requêtes SELECT
Je me demande quel est l'avantage d'utiliser SELECT WITH (NOLOCK)
sur une table si les seuls autres requêtes touchant la table SELECT
requêtes.
Comment est-ce géré par SQL Server? Une requête SELECT
bloquerait-elle une autre requête SELECT
?
J'utilise SQL Server 2012 et un Linq-to-SQL DataContext
.
(modifier)
Sur la performance:
- un 2ème
SELECT
devrait-il attendre qu'un 1erSELECT
se termine si vous utilisez unSELECT
verrouillé? - par Rapport à une
SELECT WITH (NOLOCK)
?
Merci.
6 réponses
Un SELECT
dans SQL Server placera un verrou partagé sur une ligne de table - et un second SELECT
nécessiterait également un verrou partagé, et ceux-ci sont compatibles les uns avec les autres.
Donc personne SELECT
ne peut bloquer un autre SELECT
.
Ce que l'indice de requête WITH (NOLOCK)
est utilisé est de pouvoir lire les données qui sont en cours d'insertion (par une autre connexion) et qui n'ont pas encore été validées.
Sans cette indication de requête, un SELECT
peut être bloqué en lisant une table par une instruction INSERT
(ou UPDATE
) en cours qui place un verrou exclusif sur les lignes (ou éventuellement une table entière), jusqu'à ce que la transaction de cette opération ait été validée (ou annulée).
Le Problème de l'indice WITH (NOLOCK)
est: vous pouvez lire des lignes de données qui ne seront pas insérées du tout, à la fin (si la transaction INSERT
est annulée) - donc votre rapport par exemple peut afficher des données qui n'ont jamais vraiment été validées dans la base de données.
Il y a un autre indice de requête qui pourrait soyez utile - WITH (READPAST)
. Cela indique à la commande SELECT
d'ignorer simplement toutes les lignes qu'elle tente de lire et qui sont verrouillées exclusivement. Le SELECT
ne bloquera pas et ne lira aucune donnée" sale " non validée-mais il peut ignorer certaines lignes, par exemple ne pas afficher toutes vos lignes dans la table.
Sur les performances, vous continuez à vous concentrer sur select.
Shared ne bloque pas les lectures.
Verrouillage partagé bloque la mise à jour.
Si vous avez des centaines de verrous partagés, il faudra un certain temps pour mettre à jour un verrou exclusif car il doit attendre que les verrous partagés soient effacés.
Par défaut, une sélection (lecture) prend un verrou partagé.
Les verrous partagés permettent aux transactions simultanées de lire (sélectionner) une ressource.
Un verrou partagé comme aucun effet sur les autres sélections (1 ou un 1000).
Le la différence est la façon dont les effets de verrouillage nolock par rapport aux effets de verrouillage partagés mettent à jour ou insèrent l'opération.
Aucune autre transaction ne peut modifier les données alors que des verrous partagés existent sur la ressource.
Un verrou partagé bloque une mise à jour!
Mais nolock ne bloque pas une mise à jour.
Cela peut avoir d'énormes impacts sur les performances des mises à jour. Il a également des inserts d'impact.
Lecture Sale (nolock) semble juste sale. Vous n'allez jamais à obtenir des données partielles. Si une mise à jour change John en Sally vous n'allez jamais à obtenir Jolly.
J'utilise beaucoup de verrous partagés pour la concurrence. Les données sont périmées dès qu'elles sont lues. Une lecture de John qui change en Sally la milliseconde suivante est des données périmées. Une lecture de Sally qui est annulée John la milliseconde suivante est des données périmées. C'est sur l'ordre de la milliseconde niveau. J'ai un dataloader que 20 heures pour s'exécuter si les utilisateurs prennent des verrous partagés et 4 heures pour exécuter les utilisateurs prennent pas de serrure. Les verrous partagés dans ce cas font que les données sont de 16 heures rassis.
N'utilisez pas nolocks mal. Mais ils ont une place. Si vous allez couper un chèque quand un octet est défini sur 1, puis le mettre à 2 lorsque le chèque est coupé-pas un temps pour un nolock.
À mon travail, nous avons un très grand système qui fonctionne sur plusieurs Pc en même temps, avec de grandes tables avec des centaines de milliers de lignes, et parfois de plusieurs millions de lignes.
Lorsque vous effectuez une sélection sur une très grande table, disons que vous voulez connaître toutes les transactions effectuées par un utilisateur au cours des 10 dernières années, et que la clé primaire de la table n'est pas construite de manière efficace, la requête peut prendre plusieurs minutes à exécuter.
Ensuite, notre application pourrait fonctionner sur de nombreux PC de l'utilisateur en même temps, l'accès à la même base de données. Donc, si quelqu'un essaie d'insérer dans la table que l'autre SELECT lit (dans les pages que SQL essaie de lire), un verrou peut se produire et les deux transactions se bloquent.
Nous avons dû ajouter un "No LOCK" à notre instruction SELECT, car c'était un énorme SELECT sur une table qui est beaucoup utilisée par beaucoup d'utilisateurs en même temps et nous avions des verrous tout le temps.
Je ne sais pas si mon exemple est assez clair? C'est une vraie vie exemple.
Je dois ajouter un commentaire important. Tout le monde mentionne que NOLOCK
ne lit que des données sales. Ce n'est pas précis. Il est également possible que vous obteniez la même ligne deux fois ou que la ligne entière soit ignorée pendant votre lecture. La raison en est que vous pouvez demander des données en même temps lorsque SQL Server rééquilibre b-tree.
Vérifier un autre fils
Https://stackoverflow.com/a/5469238/2108874
Http://www.sqlmag.com/article/sql-server/quaere-verum-clustered-index-scans-part-iii.aspx)
Avec L'indice NOLOCK (ou en définissant le niveau d'isolement de la session à lire non validée), vous dites à SQL Server que vous n'attendez pas de cohérence, donc il n'y a aucune garantie. Gardez à l'esprit que les "données incohérentes" ne signifient pas seulement que vous pourriez voir des modifications non validées qui ont été plus tard annulé, ou des changements de données dans un état intermédiaire de la transaction. cela signifie également que dans une requête simple qui analyse Toutes les données de table/index, SQL Server peut perdre la position d'analyse, ou vous pourriez finir par obtenir la même ligne deux fois.
Le SELECT WITH (NOLOCK)
permet la lecture de données non validées, ce qui équivaut à avoir le niveau d'isolement READ UNCOMMITTED
défini sur votre base de données. Le mot clé NOLOCK
permet un contrôle plus fin que la définition du niveau d'isolement sur l'ensemble de la base de données.
, Wikipédia a un article utile: Wikipédia: l'Isolement (systèmes de base de données)
Il est également discuté en détail dans d'autres articles stackoverflow.
Select with no lock-sélectionne les enregistrements qui peuvent / peuvent ne pas être insérés. vous lirez des données sales.
Par exemple-disons qu'une transaction insère 1000 lignes, puis échoue.
Lorsque vous sélectionnez - vous obtiendrez les 1000 lignes.