2012-03-28 4 views
2

J'ai la procédure stockée suivante. Il est destiné à obtenir un nom. Si le nom existe dans une table, il renvoie son ID correspondant. S'il n'existe pas encore, il crée un nouvel ID et l'ajoute à la table avec le nouvel ID. Le problème est que lorsque je l'exécute sur plusieurs threads qui utilisent le même nom (pas encore dans le tableau), je reçois parfois le nom plusieurs fois, avec les ID suivants. Ce que je voudrais, c'est que les transactions se bloquent lorsqu'une autre transaction est en cours, de sorte que le nom ne rentre dans la base de données qu'une seule fois.Comment synchroniser entre les transactions

Existe-t-il un niveau d'isolement ou un indice de sélection que je devrais utiliser? Y a-t-il une autre façon de faire cela?

CREATE PROCEDURE [dbo].[sp_createID] 
@name varchar(max) 
AS 
BEGIN 
SET NOCOUNT ON; 
BEGIN TRAN 
    DECLARE @id as int 
    SELECT @id=Id FROM MyTbl WHERE [email protected] 
    IF @id IS NULL 
    BEGIN 
     UPDATE idGeneratorTbl SET lastkey=lastkey+1 
     SELECT @id=lastKey FROM idGeneratorTbl 
     INSERT INTO MyTbl VALUES(@id, @name) 
    END 
    SELECT @id 
COMMIT   
END 

Répondre

1

Les deux processus doivent être sur la même transaction pour obtenir ce que vous voulez.

Vous pouvez y parvenir en supprimant le contrôle de transaction dans le processus [sp_generateNewId].

Pour votre information, vous n'avez pas à vous soucier de génération de clés, pourquoi ne vous venez pas créer un champ d'identité

+0

je me suis déplacé le code sp_generateNewId dans le code sp_createID, de supprimer le contrôle des transactions supplémentaires. Malheureusement, cela n'aide pas. Je connais le champ IDENTITY. Nous l'utilisons dans de nouvelles tables, mais ce sont de vieilles tables qui accompagnent notre produit depuis de nombreuses années, et je préférerais ne pas les changer pour le moment. –

+0

C'est bizarre, je pense que la transaction libère le verrou sur la table MyTbl après sa lecture, et non après que la transaction soit validée. essayez de faire "SELECT @ id = Id de MyTbl WHERE nom = @ nom" avec TABLOCKX ou XLOCK Voir l'explication sur: http://msdn.microsoft.com/en-us/library/ms187373.aspx – Diego

+0

@Shahar Ceux-ci sont imbriqués transactions. La validation interne ne s'engage pas du tout, donc tous les verrous sont conservés jusqu'à la validation externe. –

Questions connexes