私は以下のストアドプロシージャを持っています。それは名前を取得するためのものです。名前がテーブルに存在する場合は、対応するIDを返します。まだ存在しない場合は、新しいIDを作成し、それを新しいIDでテーブルに追加します。トランザクション間の同期方法
問題は、同じ名前(まだテーブルにはない)を使用する複数のスレッドでこれを実行すると、後で複数のIDが入力されることがあります。
私が望むのは、別のトランザクションが実行されている間にトランザクションがブロックされ、その名前がデータベースに1回だけ入ることです。
使用する必要がある分離レベルまたは選択ヒントはありますか?これを行う別の方法がありますか?
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
を作成しない、鍵生成を心配する必要はありません。残念ながら、これは役に立たない。 私はIDENTITYフィールドを認識しています。私たちは新しいテーブルでそれを使用していますが、これは私たちの製品に長年携わってきた古いテーブルなので、現時点では変更したくありません。 –
thats weird、トランザクションがコミットされた後ではなく、トランザクションがMyTblテーブルの読み込み後にロックを解放していると思います。 TABLOCKXまたはXLOCKを使用して「SELECT @ id = Id FROM MyTbl WHERE name = @ name」を実行してみてください。http://msdn.microsoft.com/en-us/library/ms187373.aspx – Diego
@Shaharこれらはネストされていますトランザクション。内部コミットはまったくコミットしないので、すべてのロックは外部コミットまで保持されます。 –