web-dev-qa-db-ja.com

自動インクリメントの主キーが数値をスキップする原因は何ですか?

次のT-SQLで作成されたテーブルがあります。

CREATE TABLE [dbo].[TableName](
    [id] [int] IDENTITY(1,1) NOT NULL
PRIMARY KEY CLUSTERED 
(
    [id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

今日、この表を見て、id列が値をスキップしていることに気付きました。

1、2、3、4、5、6、7、8、9、10、11、12、13、14、15、16、17、18、19、20、21、22、23、24、25、 26、27、1027、1028、1029、1030、1031、1032、1033、1034、1035、2034、2035、3034

私はこれや何も心配していません(私のアプリケーションは主キーが何であるかを気にしていません)。 「ジャンプ」が発生するたびに1000ジャンプするという、一種のパ​​ターンがあるようです。

私のアプリケーションは、エンティティフレームワークを使用してこれらの行を挿入します(違いがある場合)。

3
Mansfield

IDENTITY列にギャップが生じる原因はたくさんありますが(ロールバック、削除)、この場合はジャンプが原因であると考えられます。これは、SEQUENCEの導入によるIDENTITYの変更が原因であると考えられます。

したがって、SQL Serverのエラーログを見ると、これらのジャンプに関連付けられた行は、SQL Serverサービスの再起動直後に挿入された、データベースがデタッチ/再アタッチされた、などです。

しかし、実際、なぜギャップを気にするのですか? すべきではない 。連続した番号のシーケンスが必要な場合は、IDENTITYの使用を停止してください。

6
Aaron Bertrand

挿入がロールバックされても、ID値はリセットされません。これは、いわゆる「スキップされた」値の1つの説明です。

2
datagod

私の答えは遅れる可能性があることを知っています。はい、これはSQLサーバーの再起動時に発生していました。詳細については ここ を参照してください(他の回答で示されています)。 SQL Server 2014では、SQL Serverの計画的な再起動があった場合にのみ、この問題が修正されました(IDが1000に増えることはありません)。

SQL Server 2012にスタートアップストアドプロシージャを追加することで、別の方法で解決しました。

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

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

ALTER PROCEDURE [dbo].[ResetOrderIdentityAfterRestart]
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';

テーブルが少ない場合、これは良い考えです。しかし、多くのテーブルで行う必要がある場合でも、この方法は機能しますが、良い方法ではありません。

1
Jeyara