web-dev-qa-db-ja.com

SQL Serverのトランザクション/ロック

「LockedBy」フィールドを持つテーブルがあります。これは、null(誰もこのレコードを編集のためにロックしていない)か、ユーザーIDを持つことができます。

アイデアは、一度に1人のチームメンバーだけがレコード(およびこのレコードに関連付けられている他のテーブルのすべてのレコード)を "チェックアウト"できるようにすることです。 SQL Serverのトランザクションでロックがどのように機能するかは本当にわかりません。

現在、ストアドプロシージャでトランザクションとセーブポイントを使用してテーブルを更新していますが、「ロック」を組み込む方法がわかりません。

BEGIN TRANSACTION TR1
BEGIN TRY

    UPDATE LOCK_TABLE SET UpdatedDate=GETDATE() WHERE ID=@ID
    --======================================================================
    --only update this table if the lock field is null; make sure no one 
    --else can modify the lock field until the whole of TR1 is committed
    --or rolled back
    --======================================================================


    --Table 1   
    SAVE TRANSACTION TR2
    BEGIN TRY
        UPDATE TABLE1 SET somefield='something' WHERE LockTableID=@ID
    END TRY
    BEGIN CATCH
        ROLLBACK TRANSACTION TR2;
        PRINT ERROR_MESSAGE();
    END CATCH

    COMMIT TRANSACTION TR1;
    --======================================================================
    --release the lock
    --======================================================================
END TRY
BEGIN CATCH
    ROLLBACK TRANSACTION TR1;
    SET @RETURN=-1;
    PRINT ERROR_MESSAGE();
END CATCH

並行プログラミングの観点からロックを理解していますが、ロックに関するSQL Serverの導入はすべて、デッドロックを防ぐこと、またはロックのさまざまな粒度を使用する方法のいずれかに関するようです。

私が欲しいのは「ここからここまで、他の人にこのストアドプロシージャを実行させない」(マルチスレッド関数のロックのような)だけだと思いますが、おそらく私は間違った角度からやっています。

トランザクションを使用すると、SQL Serverは自動的に必要な処理を実行しますか?このストアドプロシージャの他の呼び出しをロックアウトできるようにするために、何か特別なことを追加する必要がありますか?

4
Kristen Hammack

SQL Serverには、非常に広範なロックオプションがあります。ほとんどは自動ですが、特定のケースで必要な場合は強制できます。さまざまなレベルでデフォルト以外のロック動作を実装することもできます。あなたが探しているもの(私が知る限り)は、rowlockと呼ばれるテーブルヒントによって最もよく処理できます。分離レベルによっては、その機能を確実にするために追加のヒントが必要になる場合があります。詳細については、次のリンクを参照してください。 https://msdn.Microsoft.com/en-us/library/ms187373.aspx

2
MvdMunnik

ラウンドアバウトのアイデア、代わりに権限を利用してください。

おそらく、使用するストアドプロシージャは、レコードのチェックインまたはチェックアウトに基づいて、他のユーザーのアクセス許可を追加または削除します。

例:ユーザーAは、レコードをチェックアウトするストアード・プロシージャーを使用し、レコードがチェックアウトされると、このユーザーにR/W特権を適用します。レコードがチェックインされると、Wが削除され、Rのみが適用されます(トリガーは、チェックアウト時に書き込み権限を持つユーザーを示すサイドテーブルへの書き込みを開始し、書き込み権限が誰にもないときにレコードをクリアします)。


例2:ユーザーBは、レコードをチェックアウトするストアドプロシージャを使用して、ユーザーのルックアップテーブルを調べ、現在のユーザーを選択します。マッピングテーブルの残りのユーザーは、レコードがチェックアウトされると、テーブルへのアクセス許可が削除されます。レコードがチェックインされると、プロシージャはマッピングテーブルを調べ、現在のユーザー以外のすべてのユーザーにアクセス許可を追加します。

2
Shaulinator