長時間実行挿入にはどのSQL Read TRANSACTION ISOLATION LEVELが必要ですか?
-
05-07-2019 - |
質問
複数の関連テーブルにデータを挿入する、実行時間の長い挿入トランザクションがあります。
この挿入が実行されているとき、MainTableからselect *を実行できません。選択は、挿入が完了するまでホイールを回転させるだけです。
これらの挿入のいくつかを同じ/重複する時間に実行します。情報が2回挿入されていないことを確認するには、最初にMainTableにクエリを実行して、エントリが存在するかどうかと、処理されたビットが設定されていないかどうかを確認します。
挿入トランザクション中に、その行のMainTable処理ビットを反転します。
そのため、テーブルを読み取り、特定の行が現在更新されているかどうかを確認できる必要があります。
Microsoft SQL 2005でこれを設定する方法に関するアイデアはありますか? トランザクション分離レベルの設定のドキュメントを参照しています。
ありがとうございます、
キース
編集:同じ挿入バッチが同時に発生するとは思わない。これらは処理中のバイナリファイルであり、そのデータはデータベースに挿入されます。データを解析して挿入する前に、ファイルが処理されていないことを確認します。チェックを行うときに、処理済みビットをfalseに設定してMainTableにすばやく挿入する前にファイルが表示されていない場合。
テーブル全体ではなく、更新される行をロックする方法はありますか?
解決
READ UNCOMMITTEDを使用する前に、プロセスを再考することをお勧めします。孤立したトランザクションには多くの正当な理由があります。 READ UNCOMMITTEDを使用すると、両方の挿入が同時に更新をチェックし、両方が重複を作成することを検出しない可能性があるため、重複が発生する可能性があります。小さいバッチに分割するか、定期的なCOMMITSを発行してください
編集
MainTableの更新をトランザクションでラップして、そのテーブルをより早く解放できますが、それでも他のテーブルと競合する可能性があります。
ie
BEGIN TRANSACTION
SELECT @ProcessedBit = ProcessedBit FROM MainTable WHERE ID = XXX
IF @ProcessedBit = False
UPDATE MainTable SET ProcessedBit = True WHERE ID = XXX
COMMIT TRANSACTION
IF @ProcessedBit = False
BEGIN
BEGIN TRANSACTION
-- start long running process
...
COMMIT TRANSACTION
END
編集してエラー回復を有効にします
BEGIN TRANSACTION
SELECT @ProcessedStatus = ProcessedStatus FROM MainTable WHERE ID = XXX
IF @ProcessedStatus = 'Not Processed'
UPDATE MainTable SET ProcessedBit = 'Processing' WHERE ID = XXX
COMMIT TRANSACTION
IF @ProcessedStatus = 'Not Processed'
BEGIN
BEGIN TRANSACTION
-- start long running process
...
IF No Errors
BEGIN
UPDATE MainTable SET ProcessedStatus = 'Processed' WHERE ID = XXX
COMMIT TRANSACTION
ELSE
ROLLBACK TRANSACTION
END
他のヒント
1つのトランザクションが進行中の別のトランザクションによって実行された変更を(コミットする前に)読み取ることができる唯一の分離レベルは次のとおりです。
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED