2016-09-12 10 views
1

トリガーを使用して関連するテーブルのロックに問題があります。SQL Serverのトリガー挿入により、コミットまでロックが発生します。

テーブルtCatalogに挿入しています(これは別のテーブルにレコードを挿入するトリガーを持っています)tSearchQueue)。 tCatalogへの挿入は、数秒かかることがある他の多くの機能を持つトランザクション内にあります。ただし、トランザクションがコミットされるまでtSearchQueueテーブルはロックされます。これを避ける方法はありますか?

INSERT INTO [dbo].[tSearchQueue] (Processed, SQL, sys_CreateDate) 
    SELECT  
     0, 'Test ' + cast(CatalogID as varchar(10)), getdate() 
    FROM   
     inserted 


BEGIN TRAN t1 
    DECLARE @catalogid int 

    INSERT INTO tCatalog (ProgramID, sys_CreatedBy, ItemNumber, Description, UOMID) 
    VALUES (233, 1263, 'brian catalog4', 'brian catalog4', 416) 

    SELECT @catalogid = SCOPE_IDENTITY() 

    INSERT INTO tCustomAttributeCatalog (CatalogID, CustomAttributeID, DefaultValue, DefaultValueRead, sys_CreatedBy) 
    VALUES (@catalogid, 299, 'No', 'No', 1263) 

    INSERT INTO tCustomAttributeCatalog (CatalogID, CustomAttributeID, DefaultValue, DefaultValueRead, sys_CreatedBy) 
    VALUES (@catalogid, 300, null, null, 1263) 

COMMIT TRAN t1 
+0

***なぜ***は 'tSearchQueue'がロックされていますか?何がこの動作の原因ですか?あなたはこれを避けることができますか? –

+0

@marc_sそれは本質的に私が求めている質問です。 tCatalogへの挿入トランザクションがまだコミットされていないため、ロックされているように見えます。私はそれを避けようとしています。 – btorkelson

+0

挿入物を 'TCatalog'に表示できますか?しかし、それだけでは別のテーブル 'TSearchQueue'をロックしてはいけません.... –

答えて

0

バックグラウンドプロセスがあり、変更の通知が必要なので、何らかの再インデックス作成ができるようです。その場合、必ずしもが間違ったであるとは限りません。なぜなら、トランザクションがコミットしていなければ、それをインデックス化してはならないからです。

だから順序は次のとおりです。

  • 挿入いくつかの他のテーブル
  • が長時間実行操作を実行しtSearchQueue
  • 挿入トランザクションに
  • 挿入tCatalog
    • トリガを開始します
    • トランザクションをコミットします。

    そして、問題はtSearchQueueを読みたいけど、それがロックされていることができないので別のプロセスです。

    オプション1:バッチでバックグラウンド操作を実行します。

    がテーブルを読み取る機会があまりにも少ないため、になると、一度に複数の行を読むと問題が解決する可能性があります。私。待ち行列を読むチャンスが得られるたびに、多くの行を読み込んで一度に処理し、それらをまとめてマークする(あるいは場合によっては削除する)必要があります。

    オプション2:可能な場合、最初の実行時間の長い操作を実行し

    • トランザクションを開始
      • トリガtSearchQueue
    • を挿入長時間実行操作
    • 挿入tCatalogを行います
    • 他のテーブルを挿入する
    • トランザクションをコミット

    他のプロセスは今tSearchQueueが短時間だけロックされて見つけました。 長時間実行される操作がファイルコピーの場合、これらはトランザクションにCopyFileTransactedを使用して含めることができます。操作が失敗した場合は、コピーを「catch」文でロールバックできます。

    オプション3:他のプロセスがテーブルを読み取るために、主にしようとしている場合はバックグラウンド・プロセスがロック

    を回避し、その後、スナップショット分離は、あなたの問題を解決することがあります。これは、その時点で存在していたコミットされた行のみを戻します。行レベルのロックと組み合わせると、問題が解決する可能性があります。

    また、バックグラウンドプロセスは、NOLOCKヒント(ダーティリード)で読み取ることがあります。これにより、後でロールバックされるトランザクションからデータを読み取る可能性があります。ただし、データが別の手順で検証されている場合(たとえば、再インデックスを必要とするオブジェクトの識別子を書き込むなど)、これは必ずしも問題ではありません。索引付けプロセスがもはや存在しないエントリや実際に変更されていないエントリに対処できる場合、偽の読み込みは問題になりません。

  • 関連する問題