0

テーブルからすべてのレコードを読み取り、それらをすべて削除することになっている単純な SQL コマンドがあります。正確な瞬間に他の誰かがこのテーブルに書き込みを行っている可能性があるため、テーブルをロックして、削除したものすべてが読み取り済みのものであることを確認したいと考えています。

BEGIN TRAN T1; 
SELECT LotID FROM fsScannerIOInvalidCachedLots WITH (TABLOCK, HOLDLOCK); 
DELETE FROM fsInvalidCachedLots; 
COMMIT TRAN T1;

本当に奇妙なことは、これが動作するように使用されていることです。テストを通じてしばらくは機能しましたが、すべてを読み込んでいるため、何かが変わったと思いますが、レコードは削除されていません。その結果、SQL Server の CPU 使用率が高くなります。これは、次に実行するときに実行にかなりの時間がかかるためです。これは、ロックに関係していると思われます。

ここで何が起こっているのでしょうか?私は両方を試しましTABLOCKTABLOCKX

更新: そうそう、言い忘れたことですが、プログラムが次に読み取りを行うまで、そのテーブルを照会することはできません。つまり、そのステートメントがコードで実行された後 (コマンドと接続が破棄された後)、Management Studio 内からそのテーブルをクエリしようとすると、ハングするだけです。これは、まだロックされていることを意味すると思います。しかし、次のデータベース接続に到達するまで呼び出しプログラムをステップ実行すると、最初の読み取りの直後にテーブルがロックされなくなります。

4

1 に答える 1

1

というSELECT名前のテーブルからデータを取得しますfsScannerIOInvalidCachedLotsが、削除は という名前の別のテーブルからのものfsInvalidCachedLotsです。

でこのクエリを実行するset xact_abort offと、無効なテーブル名によるエラーによってトランザクションが中止されることはありません。実際、select @@trancountはアクティブなトランザクションがあることを示し、トランザクションがアクティブでエラーが発生していないselect xact_state()ことを意味する 1 を返します。

一方、set xact_abort onでは、トランザクションは中止されます。 select @@trancount0 を返し、0select xact_state()を返します (アクティブなトランザクションはありません)。

それらの詳細については、MSDN の@@trancountおよびxact_state()を参照してください。

于 2013-01-22T19:47:09.113 に答える