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
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. –
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
@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. –