Question

Je fais partie d'une équipe qui crée un site Web basé sur ADO.NET. Nous avons parfois plusieurs développeurs et un outil de test automatisé travaillant simultanément une copie de développement de la base de données.

Nous utilisons le niveau d'isolation de capture instantanée qui, à ma connaissance, utilise une concurrence optimiste: au lieu de verrouiller, il espère le meilleur et lève une exception si vous essayez de valider une transaction si les lignes affectées ont été modifiées par une autre partie lors de la transaction.

Pour utiliser le niveau d'isolation de capture instantanée, nous utilisons:

ALTER DATABASE <database name>
SET ALLOW_SNAPSHOT_ISOLATION ON;

et en C #:

Transaction = SqlConnection.BeginTransaction(IsolationLevel.Snapshot);

Notez qu'IsolationLevel Snapshot n'est pas identique à ReadCommitted Snapshot, que nous avons également essayé, mais que nous n'utilisons pas actuellement.

Lorsque l'un des développeurs entre en mode débogage et met en pause l'application .NET, ils établissent une connexion avec une transaction active pendant le débogage. Maintenant, je ne m'attendrais pas à ce que ce ne soit pas un problème - après tout, toutes les transactions utilisent un niveau d'isolation de capture instantanée. Ainsi, lorsqu'une transaction est suspendue, les autres transactions devraient pouvoir se poursuivre normalement, car la transaction suspendue ne détient aucun verrou. Bien entendu, lorsque la transaction en pause est terminée, elle est susceptible de détecter un conflit. mais c'est acceptable tant que les autres développeurs et les tests automatisés peuvent se dérouler sans entrave.

Cependant, dans la pratique, lorsqu'une personne arrête une transaction lors du débogage, tous les autres utilisateurs de base de données essayant d'accéder aux mêmes lignes sont bloqués, et ce, malgré l'utilisation du niveau d'isolation de capture instantanée.

Quelqu'un sait-il pourquoi cela se produit et / ou comment je peux obtenir une véritable concurrence simultanée optimiste (non bloquante)? ??

La résolution (une malheureuse pour moi) : Remus Rusanu a noté que les rédacteurs bloquent toujours les autres rédacteurs; ceci est sauvegardé par MSDN - cela ne dit pas tout à fait, mais mentionne seulement d'éviter les verrous lecteur-écrivain. En bref, le comportement que je souhaite n’est pas implémenté dans SQL Server.

Était-ce utile?

La solution

Le niveau d’isolation SNAPSHOT affecte, comme tous les niveaux d’isolation, uniquement les lectures. Les écritures se bloquent encore. Si vous pensez que ce que vous voyez sont des blocs lus, vous devez alors étudier plus en profondeur et consulter les types de ressource et les noms de ressource sur lesquels le blocage a lieu (wait_type et wait_resource dans sys.dm_exec_requests ).

Je ne conseillerais pas de modifier le code afin de prendre en charge un scénario dans lequel les développeurs observent le débogueur pendant des minutes. Si vous pensez que ce scénario peut se reproduire en production (c'est-à-dire que le client se bloque), l'histoire est différente. Pour obtenir ce que vous voulez, vous devez minimiser les écritures et effectuer toutes les écritures à la fin de la transaction, en un seul appel qui est validé avant le renvoi. De cette façon, aucun client ne peut conserver X verrous pendant une longue période (impossible de raccrocher avec des verrous X). En pratique, cela est assez difficile à obtenir et demande aux développeurs beaucoup de discipline dans la manière dont ils écrivent le code d'accès aux données.

Autres conseils

Avez-vous examiné les verrous lorsqu'un développeur met la transaction en pause? De plus, le simple fait d'activer le niveau d'isolation d'instantané n'a pas beaucoup d'effet. Avez-vous activé ALLOW_SNAPSHOT_ISOLATION?

Voici les étapes:

ALTER DATABASE <databasename>
SET READ_COMMITTED_SNAPSHOT ON;
GO

ALTER DATABASE <database name>
SET ALLOW_SNAPSHOT_ISOLATION ON;
GO

Une fois la base de données activée pour l'isolation de capture instantanée, les développeurs et les utilisateurs doivent ensuite demander que leurs transactions soient exécutées dans ce mode de capture instantanée. Cela doit être fait avant de commencer une transaction, soit par une directive côté client sur l'objet de transaction ADO.NET, soit dans leur requête Transact-SQL à l'aide de l'instruction suivante:

SET TRANSACTION ISOLATION LEVEL SNAPSHOT

Raj

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top