2010-02-24 3 views
0

Nous avons un système C# qui crée une anomalie que nous ne pouvons pas atteindre en bas avec SQL (SQL2k5). En l'occurrence, deux processus distincts s'exécutent simultanément sur la même table, tous deux s'exécutant à l'intérieur de leur propre transaction dans deux composants COM + desservis différents sur deux clusters différents. Les deux parlent à Order et OrderItem des tables SQL. Les deux fonctionnent au niveau d'isolement READ COMMITTED.Transaction SQL Bizarrerie avec les processus concurrents de C#

Travail 1: Chargement d'une commande et un ou plus d'articles dans ces tableaux.

Job 2: Une tâche planifiée qui se produit toutes les quelques minutes de ladite sélection tables trouver toutes les commandes qui ont été entièrement traitées.

Le problème: Ce que nous avons trouvé que quatre fois au cours des huit derniers mois travail 2 a réagi à un ordre partiellement chargé du travail 1, avant le travail 1 a dûment rempli (comme un élément de l'ordre n'a pas été stocké, il est à un état fini, donc est vu par le travail que le reste de la commande est encore à charger).

De l'enquête, alors que l'emploi 1 est en cours, nous ne pouvons pas faire un:

select * de l'ordre

une fois qu'une commande a été insérée en elle. Cependant, nous pouvons faire:

select * fromOrder o jointure interne OrderItem oi sur oi.orderid = o.id

en même temps (pourquoi est-ce?). Lors d'une recherche reproduisant les mêmes circonstances, nous ne pouvons pas obtenir le travail 2 pour voir un ordre partiellement créé du travail 1, il renvoie des lignes mais jamais l'ordre n'est inséré par le travail 1. Cependant, c'est exactement ce qui se passe dans notre environnement en direct!

Quelqu'un a-t-il un aperçu de la raison pour laquelle cela se produit?

Répondre

0

Je voudrais essayer d'annuler un travail effectué par le travail 1 comme une expérience pour confirmer que tout ce que vous pensez est inclus dans la transaction est effectivement supprimé lorsque l'annulation se produit. J'ai, comme vous, soupçonné que vous ne serez jamais capable de lire des données provenant d'une transaction différente, qui seraient supprimées par une restauration lors de l'utilisation de READ COMMITTED. Le fait que vous soyez en mesure de lire des lignes suggère que certaines d'entre elles pourraient entrer en dehors du contexte de la transaction. La pensée suivante est d'examiner la signification de READ COMMITTED. Ce niveau d'isolement garantit que les données que vous lisez ont été validées par une transaction, mais ne garantit pas nécessairement qu'elles ne peuvent toujours pas changer suite à une autre transaction. Comparez cela avec REPEATABLE READ où toutes les données restent verrouillées jusqu'à la fin de la transaction, ou SERIALIZABLE, qui essaie de se comporter comme si toutes les transactions étaient exécutées dans l'ordre. Je soupçonne que si vous changez votre verrouillage à SERIALIZABLE (le plus restrictif) ce problème particulier ne se produirait pas, mais cela peut être exagéré.Après avoir considéré la signification de READ COMMITTED par rapport aux autres niveaux d'isolation, je suspecte que le comportement que vous voyez est naturel dans ce niveau d'isolation parce que les lignes que vous avez insérées seront en fait les lignes qui seront toujours là à la fin de la transaction. Je pense que READ COMMITTED n'est pas destiné à garantir que la requête renvoie un ensemble complet de lignes (ce qui nécessiterait un verrou de plage tel qu'imposé par SERIALIZABLE), mais seulement que les lignes individuelles que vous lisez ont été complètement insérées (ainsi vous ne lis pas une rangée partielle). Je peux me tromper, mais étant donné le comportement que vous décrivez, c'est mon soupçon. Si vous devez vous assurer que l'ensemble des lignes est complet, je pense que vous avez besoin d'une isolation SERIALIZABLE.

Quelle transaction doit être SERIALISABLE? De toute évidence, s'ils sont tous les deux SERIALIZABLE, cela devrait fonctionner. Mais il peut être possible de faire un seul d'entre eux SERIALIZABLE et toujours obtenir le bon comportement. Mes pouvoirs mentaux en ce moment ne sont pas à la hauteur de la tâche de déterminer ce qui doit vraiment être SERIALISABLE, mais peut-être que certains commentaires d'autres apporteront un éclairage supplémentaire.

0

Le problème est que lorsque vous ouvrez une transaction et ajoutez quelques lignes, ces lignes sont verrouillées jusqu'à ce que la transaction soit validée.

Lorsque vous effectuez un select qui inclut les lignes verrouillées, vous devez les déverrouiller en validant ou en annulant la transaction avant de pouvoir sélectionner SELECT.

Questions connexes