2008-10-30 11 views
1

J'ai une transaction d'insertion en cours d'exécution qui insère des données dans plusieurs tables liées.Quel SQL lire TRANSACTION ISOLATION LEVEL est-ce que je veux pour insérer longtemps?

Lorsque cette insertion est en cours d'exécution, je ne peux pas effectuer un select * à partir de MainTable. La sélection tourne simplement ses roues jusqu'à ce que l'insertion soit terminée.

Je vais effectuer plusieurs de ces insertions au même temps/chevauchement. Pour vérifier que les informations ne sont pas insérées deux fois, j'interroge d'abord le MainTable pour voir si une entrée est là et que son bit traité n'est pas défini.

Lors de la transaction d'insertion, elle retourne le bit traité MainTable pour cette ligne.

Je dois donc pouvoir lire la table et savoir si la ligne spécifique est en cours de mise à jour.

Des idées sur la façon de configurer cela dans Microsoft SQL 2005? Je regarde la documentation SET TRANSACTION ISOLATION LEVEL.

Merci,
Keith

EDIT: Je ne pense pas que le même lot d'insertion se produira en même temps. Ce sont des fichiers binaires en cours de traitement et leurs données insérées dans la base de données. Je vérifie que le fichier n'a pas été traité avant d'analyser et d'insérer les données. Lorsque je fais la vérification, si le fichier n'a pas été vu avant je fais une insertion rapide dans le MainTable avec le bit traité défini faux.

Existe-t-il un moyen de verrouiller la ligne mise à jour au lieu de la table entière?

Répondre

2

Vous voudrez peut-être repenser votre processus avant d'utiliser LIRE UNCOMMITTED. Il y a beaucoup de bonnes raisons pour les transactions isolées. Si vous utilisez READ UNCOMMITTED, vous pouvez toujours obtenir des doublons car il est possible que les deux inserts vérifient les mises à jour en même temps et ne trouvent pas les doublons en même temps. Essayez le casser en petits lots ou émettez ENGAGE périodiques

EDIT

Vous pouvez envelopper la mise à jour maintable dans une transaction qui libéreront cette table plus rapide, mais vous pouvez toujours obtenir des conflits avec les autres tables.

-à-dire

BEGIN TRANSACTION 

SELECT @ProcessedBit = ProcessedBit FROM MainTable WHERE ID = XXX 

IF @ProcessedBit = False 
    UPDATE MainTable SET ProcessedBit = True WHERE ID = XXX 

COMMIT TRANSACTION 

IF @ProcessedBit = False 
BEGIN 
    BEGIN TRANSACTION 
    -- start long running process 
    ... 
    COMMIT TRANSACTION 
END 

EDIT pour permettre la récupération d'erreur

BEGIN TRANSACTION 

SELECT @ProcessedStatus = ProcessedStatus FROM MainTable WHERE ID = XXX 

IF @ProcessedStatus = 'Not Processed' 
    UPDATE MainTable SET ProcessedBit = 'Processing' WHERE ID = XXX 

COMMIT TRANSACTION 

IF @ProcessedStatus = 'Not Processed' 
BEGIN 
    BEGIN TRANSACTION 
    -- start long running process 
    ... 

    IF No Errors 
    BEGIN 
     UPDATE MainTable SET ProcessedStatus = 'Processed' WHERE ID = XXX 
     COMMIT TRANSACTION 
    ELSE 
     ROLLBACK TRANSACTION 

END 
+0

DJ, Le problème que je verrais avec votre exemple est que le ProcessedBit est réglé vrai avant que le long processus est RAN. Si le long processus des erreurs, alors il me reste le ProcessedBit = true. Merci pour votre aide. Keith –

+0

Ouais, vous devez avoir un champ de statut à la place - avec trois valeurs: Non traité, en cours de traitement, et traité –

0

Le seul niveau d'isolement qui permet une transaction à lire les modifications effectuées par une autre transaction en cours (avant de s'engager) est:

SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED