13

言い換えれば、次の「cursoring」アプローチが機能することが保証されていますか。

  1. DBから行を取得する
  2. 返されたレコードから最大のIDを保存して、後で使用できるようにします。LastMax
  3. 後で、"SELECT * FROM MyTable WHERE Id > {0}", LastMax

それが機能するためには、ステップ1で取得しなかったすべての行のIdが。より大きいことを確認する必要がありLastMaxます。これは保証されていますか、それとも奇妙な競合状態に遭遇する可能性がありますか?

4

5 に答える 5

20

いかなる状況においても、現在の最大値以下の値を取得できる可能性があることを保証しますか?いいえ、そのような保証はありません。とはいえ、そのシナリオが発生する可能性のある状況は限られています。

  1. 誰かがID挿入を無効にして、値を挿入します。
  2. 誰かがID列を再シードします。
  3. 誰かが増分値の符号を変更します(つまり、+ 1ではなく-1に変更されます)

これらの状況のいずれも想定しない場合、次の値が既存の値よりも低い状況を作成する競合状態から安全です。とはいえ、行がID値の順序でコミットされるという保証はありません。例えば:

  1. トランザクションを開き、ID列を使用してテーブルに挿入します。値42を取得するとします。
  2. 同じテーブルに別の値を挿入してコミットします。値43を取得するとします。

最初のトランザクションがコミットされるまで、43は存在しますが、42は存在しません。ID列は単に値を予約するだけであり、コミットの順序を指示するものではありません。

于 2010-05-13T17:51:18.120 に答える
4

トランザクションの期間によっては、これがうまくいかない可能性があると思います。次の一連のイベントについて考えてみます。

  1. トランザクションAが開始します
  2. トランザクションAは挿入を実行します-これにより、ID列に新しいエントリが作成されます
  3. トランザクションBが開始します
  4. トランザクションBは挿入を実行します-これにより、ID列に新しいエントリが作成されます
  5. トランザクションBはコミットします
  6. コードは選択を実行し、2番目のトランザクションからのID値を確認します
  7. トランザクションAのコミット-

トランザクションAによって挿入された行は、コードによって検出されることはありません。手順6が実行されたとき、まだコミットされていません。また、次のクエリが実行されると、クエリが探しているよりもID列の値が低いため、見つかりません。

読み取り-コミットされていない分離モードでクエリを実行すると、機能する可能性があります

于 2010-05-13T18:34:35.243 に答える
2

IDは、常にIDを定義する増分に従います。

IDENTITY [(シード、インクリメント)] http://msdn.microsoft.com/en-us/library/aa933196(SQL.80).aspx

これは正または負の場合があります(前方または後方に増分させることができます)。IDを前方にインクリメントするように設定すると、ID値は常に前の値よりも大きくなりますが、INSERTをロールバックすると、一部を見逃す可能性があります。

はい、ID増分を正の値に設定すると、ループロジックが機能します。

于 2010-05-13T17:40:56.107 に答える
1

レコードが挿入されて取得できないのは、誰かがID挿入をオンにして、スキップされたID(または場合によっては負の数)にレコードを手動で挿入した場合のみです。これは非常にまれなケースであり、通常はシステム管理者のみが実行します。たとえば、誤って削除されたレコードを再挿入するために実行される場合があります。

于 2010-05-13T17:40:49.747 に答える
0

SQL Serverが保証する唯一のことは、IDENTITY列が常にインクリメントされることです。

ただし、考慮事項:

  1. INSERTが失敗した場合、IDENTITY列はとにかくインクリメントされます。
  2. ロールバックが発生した場合、IDENTITY列は前の値に戻りません。

これが、SQLServerがシーケンシャルINDENTITYを保証しない理由を説明しています。

DBCCコマンドを使用して、そのようにIDENTITY列をリセットする方法があります。ただし、その前に、次のことを考慮してください。

  1. IDENTITY列が他のテーブルから参照されていないことを確認してください。外部キーが更新されない可能性があるため、大きな問題が発生します。
  2. SET IDENTITY_INSERT ON / OFF命令を使用すると、行を挿入するときにIDENTITYを手動で指定できます(後でオンにすることを忘れないでください)。

IDENTITY列は、DBRMで変更されない最も重要な要素の1つです。

これがあなたを助けるべきリンクです:IDENTITY列を理解する

編集: LastMaxのIDENTITY列は、挿入された行ごとに常に増分するため、あなたがしているように見えることは機能します。それで:

  1. データテーブルから行を選択します。
  2. LastMax状態を保存します。
  3. Id>LastMaxの行を選択します。

3)IDENTITY列がLastMaxよりも大きい行のみを選択するため、LastMaxが保存されたために挿入されます。

于 2010-05-13T17:55:18.547 に答える