137

FeeSQL Server 2012の「ReceiptNo」列にある私のテーブルの1つで、データベースIDの増分が、次の2つのことに応じて、1ではなく100に急上昇し始めました。

  1. 1205446の場合は1206306にジャンプし、1206321の場合は1207306にジャンプし、1207314の場合は1208306にジャンプします。最後の3桁は一定のままです。つまり、ジャンプするたびに306になります。次の図に示すように発生します。

  2. この問題は、コンピューターを再起動すると発生します

ここに画像の説明を入力してください

4

6 に答える 6

171

SQL Server 2012 以降のパフォーマンスの向上により、この動作が発生しています。

IDENTITY列に値を割り当てint、サービスを再起動すると未使用の値が「失われる」可能性がある場合、デフォルトで 1,000 のキャッシュ サイズが使用されるようになりました ( bigint/のキャッシュ サイズは 10,000 ですnumeric)。

これはドキュメントに記載されています

SQL Server は、パフォーマンス上の理由から ID 値をキャッシュする場合があり、割り当てられた値の一部は、データベースの障害時またはサーバーの再起動時に失われる可能性があります。これにより、挿入時に ID 値にギャップが生じる可能性があります。ギャップが許容できない場合、アプリケーションは独自のメカニズムを使用してキー値を生成する必要があります。オプションでシーケンス ジェネレータを使用すると、NOCACHEコミットされないトランザクションへのギャップを制限できます。

あなたが示したデータから、これは12月22日のデータ入力後に発生したように見え、再起動したときにSQL Serverが値を予約しました1206306 - 1207305。12 月 24 ~ 25 日のデータ入力が行われた後、もう一度再起動すると、SQL Server1207306 - 1208305は 28 日のエントリに表示される次の範囲を予約しました。

異常な頻度でサービスを再起動しない限り、「失われた」値がデータ型で許可されている値の範囲に大きな影響を与える可能性は低いため、最善のポリシーはそれについて心配しないことです。

これが何らかの理由であなたにとって本当の問題である場合、いくつかの可能な回避策があります...

  1. SEQUENCEたとえば、ID 列の代わりに を使用して、より小さいキャッシュ サイズを定義NEXT VALUE FORし、列のデフォルトで使用することができます。
  2. または、トレース フラグ 272 を適用IDENTITYして、2008 R2 までのバージョンのように割り当てをログに記録します。これは、すべてのデータベースにグローバルに適用されます。
  3. または、最近のバージョンの場合は、実行ALTER DATABASE SCOPED CONFIGURATION SET IDENTITY_CACHE = OFFして特定のデータベースの ID キャッシュを無効にします。

これらの回避策のいずれもギャップがないことを保証するものではないことに注意してください。IDENTITYこれは、テーブルへの挿入をシリアル化することによってのみ可能になるため、によって保証されたことはありません。ギャップレスカラムが必要な場合は、またはいずれIDENTITYか以外のソリューションを使用する必要がありますSEQUENCE

于 2013-01-03T19:57:08.587 に答える
26

私の答えがパーティーに遅れるかもしれないことはわかっています。しかし、SQL Server 2012 にスタートアップ ストアド プロシージャを追加することで、別の方法で解決しました。

マスター DB に次のストアド プロシージャを作成します。

USE [master]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[ResetTableNameIdentityAfterRestart]
AS
BEGIN

begin TRAN
    declare @id int = 0
    SELECT @id =  MAX(id) FROM [DatabaseName].dbo.[TableName]
    --print @id
    DBCC CHECKIDENT ('[DatabaseName].dbo.[TableName]', reseed, @id)
Commit

END

次に、次の構文を使用してスタートアップに追加します。

EXEC sp_procoption 'ResetOrderIdentityAfterRestart', 'startup', 'on';

テーブルが少ない場合、これは良い考えです。ただし、多くのテーブルに対して行う必要がある場合、この方法は引き続き機能しますが、良い考えではありません。

于 2015-03-30T23:31:21.293 に答える
8

ID 値がジャンプする理由は多数考えられます。それらは、ロールバックされた挿入からレプリケーションのための ID 管理にまで及びます。あなたのケースでこれを引き起こしているのは、システムでしばらく時間を費やさないとわかりません。

ただし、ID 列が連続していると想定することは決してできないことを知っておく必要があります。ギャップの原因となるものが多すぎます。

これについての詳細は、http ://sqlity.net/en/792/the-gap-in-the-identity-value-sequence/ を参照してください。

于 2013-01-03T19:59:50.377 に答える