IDENTITY_INSERTは並行性にどのように影響しますか?


11

投稿に不具合があり、サポートが終了したサードパーティのSAPアドオンを使用してお客様を支援しようとしています。

特定の状況下では、投稿キューテーブルから投稿アーカイブテーブルへの不完全な投稿をアーカイブします。これらのアーカイブされた結果をキューに戻す必要があります。

キューIDはID列であり、同じにしたいと思います。

問題は、identity_insertをオン/挿入/ identity_insertオフにすると、キューエントリを作成し、ID列が自動的に生成されることを期待するプロセスとの同時実行性に関して何が期待できるでしょうか。

そのような振る舞いを実証するための最良の方法へのポインタも同様に大歓迎です。

回答:


8

IDENTITY_INSERT ON単独で設定しても同時実行性は排除されません。これにより、テーブルに排他ロックが設定されず、簡単なスキーマ安定性(Sch-S)ロックのみが設定されます。

理論的には、デフォルトの動作では、セッション1でこれを行うことができます。

BEGIN TRANSACTION;

-- 1
SET IDENTITY_INSERT dbo.tablename ON;

-- 2
INSERT dbo.tablename(id, etc) VALUES(100, 'foo'); -- next identity is now 101

-- 3
INSERT dbo.tablename(id, etc) VALUES(101, 'foo'); -- next identity is now 102

-- 4
SET IDENTITY_INSERT dbo.tablename OFF;

COMMIT TRANSACTION;

別のセッションでは、あなたはこれが可能ポイント1、2、3または4で、テーブルに行を挿入することができますように見える、2と3の間で起こるすべての挿入のために何が起こるかを除いて、良いことのように自動生成された値がトリガということです別のセッションでは、ステートメント2の結果に基づいています。そのため、101が生成され、ステートメント3は主キー違反で失敗します。これは、いくつかWAITFORのs を使用して設定およびテストするのがかなり簡単です。

-- session 1
-- DROP TABLE dbo.what;
CREATE TABLE dbo.what(id INT IDENTITY PRIMARY KEY);
GO
BEGIN TRANSACTION;

SET IDENTITY_INSERT dbo.what ON;

INSERT dbo.what(id) VALUES(32);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(33);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(34);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(35);
WAITFOR DELAY '00:00:05';
INSERT dbo.what(id) VALUES(36);

SET IDENTITY_INSERT dbo.what OFF;

COMMIT TRANSACTION;

そのバッチが開始したら、別のウィンドウでこのバッチを開始します。

-- session 2
INSERT dbo.what DEFAULT VALUES;
WAITFOR DELAY '00:00:01';
GO 20

セッション2では、1〜20の値のみを挿入する必要があります。ただし、基になるIDは手動挿入セッション1によって更新されているため、ある時点で、セッション2はセッション1が終了した場所を取得し、32、33、または34などを挿入します。これは可能ですが、次に、セッション1は次の挿入でPK違反で失敗します(どちらが勝つかはタイミングの問題である場合があります)。

これを回避する1つの方法はTABLOCK、最初の挿入でを呼び出すことです。

INSERT dbo.what WITH (TABLOCK) (id) VALUES(32);

これにより、アーカイブされた行の移動が完了するまで、他のユーザーがこのテーブルを挿入しようとする(実際には何もしない)ことがブロックされます。これは確かに、並行性を絞るが、これは、あなたが道であるたい仕事に遮断します。うまくいけば、これは他の人を常にブロックしているような頻繁な頻度で起こっていることではありません。

他のいくつかの回避策:

  • IDENTITY生成された値を気にしないでください。誰も気にしない?元の値が非常に重要な場合は、(代理としてを使用UNIQUEIDENTIFIERして別のテーブルで生成されるIDENTITY場合があります)を使用します。
  • アーカイブプロセスを変更して、「ソフト削除」を使用するようにします。この場合、何かが最初にアーカイブ済みとしてマークされ、アーカイブは後日まで永続化されません。次に、それらを元に戻そうとしているプロセスは、直接更新を実行して、ソフト削除フラグを修正するだけです。

説明してくれて、ありがとうございます。私は、これらのIDフィールドを作成するサポート対象外の製品を支援するスタンドアロンユーティリティを作成しています。私はそれがどのように動作するかを制御できません。
メタファー2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.