3

次のT-SQLコードがあります。

SET TRANSACTION ISOLATION LEVEL SERIALIZABLE
BEGIN TRANSACTION T1_Test

    /*This is a dummy table used for "locking" 
    and it doesn't contain any meaningful data.*/        
    UPDATE lockTable 
        SET ID = 1    
        WHERE ID = 1

    DECLARE @Count TINYINT 

    SELECT @Count = COUNT(*)
    FROM debugSP 

    WAITFOR DELAY '00:00:5';

    INSERT INTO debugSP 
        (DateCreated, ClientId, Result)
    SELECT 
        GETDATE(), @@SPID, @Count

COMMIT TRANSACTION T1_Test

コメントでマークされた「ロック」ハックを使用して、排他ロックを取得しています。

注:テスト目的でステートメントを分割し、途中でWAITFORコマンドを追加することでATOMIC性を破ったため、TABLOCKXまたはUPDLOCKヒントの使用は機能しません。私はそのようなものは欲しくない:

INSERT INTO debugSP (DateCreated, ClientId, Result)
SELECT GETDATE(), @@SPID, COUNT(*) 
FROM debugSP

これは、2つの同時セッション(ロックテーブルを使用)を実行した後の正しい結果です。

Id DateCreated           ClientId Result
-- ----------------------- -------- ------
 1 2011-03-17 15:52:12.287       66      0
 2 2011-03-17 15:52:24.534       68      1

これは、ロックをコメントアウトしてコードを実行した場合の誤った結果です。

Id DateCreated           ClientId Result
-- ----------------------- -------- ------
 1 2011-03-17 15:52:43.128       66      0
 2 2011-03-17 15:52:46.341       68      0

そのようなハッキングなしでトランザクション全体の排他的ロックを取得するより良い方法はありますか?

4

2 に答える 2

7

投稿されたコードからあなたが何をしようとしているのか正確にはわかりません。そのコードへのアクセスをシリアル化しようとしているだけだと思いますか?もしそうsp_getapplockなら、ロックをかけるために使用する新しいダミーテーブルを作成する代わりに、必要なことを実行する必要があります。

詳細はこちら

于 2011-03-17T16:32:49.623 に答える
1

繰り返し可能な読み取り分離を使用するトランザクションのスコープ内で、ロックヒントWITH(XLOCK、ROWLOCK)を使用できます。シリアル化可能な分離では、読み取り操作でデフォルトで排他ロックが取得されるため、特定のトランザクションを並行して正常に再生する必要がある場合は、作成時にその1つのトランザクションのシリアル化レベルを上げることができます(これは実行中です。これはそうではありません)。ハックではなく、状況に応じて物事が行われる方法です)。

于 2011-03-17T16:34:56.867 に答える