web-dev-qa-db-ja.com

7番目のエントリでSQL Server 2012の列IDの増分が6から1000以上にジャンプする

SQL Server 2012データベースの自動ID int列が正しく増加しないという奇妙なシナリオがあります。

たとえば、主キーとしてint auto identityを使用するテーブルがあり、散発的にインクリメントをスキップしているとします。たとえば、

1、2、3、4、5、1004、1005

これは、非常にランダムな時間にランダムな数のテーブルで発生し、傾向を見つけるためにそれを複製することはできません。

これはどうしてですか?停止させる方法はありますか?

121
Andy Clark

これはすべて完全に正常です。 MicrosoftはSQL Server 2012にsequencesを追加しました。最後に、IDキーの生成方法を追加および変更できます。いくつかの説明については、 こちら をご覧ください。

古い動作を行いたい場合は、次のことができます。

  1. トレースフラグ272を使用-これにより、生成されたID値ごとにログレコードが生成されます。このトレースフラグをオンにすると、ID生成のパフォーマンスが影響を受ける場合があります。
  2. nO CACHE設定でシーケンスジェネレーターを使用する( http://msdn.Microsoft.com/en-us/library/ff878091.aspx
75
Mithrandir

同じ問題が発生し、SQL Server 2012で次のバグレポートが見つかりました。関連する場合は、問題の原因となる条件を確認してください。 フェールオーバーまたは再起動の結果、IDが再シードされます

4
yoosha

トレースフラグ272は多くの場合に機能する可能性がありますが、ホストされているSql Server Expressのインストールでは確実に機能しません。そこで、IDテーブルを作成し、INSTEAD OFトリガーを使用してこれを使用します。これが他の誰かに役立つこと、および/または他の人に私のソリューションを改善する機会を与えることを願っています。最後の行では、最後に追加されたID列を返すことができます。通常、これを使用して単一の行を追加するため、これは単一の挿入行のIDを返すように機能します。

IDテーブル:

CREATE TABLE [dbo].[tblsysIdentities](
[intTableId] [int] NOT NULL,
[intIdentityLast] [int] NOT NULL,
[strTable] [varchar](100) NOT NULL,
[tsConcurrency] [timestamp] NULL,
CONSTRAINT [PK_tblsysIdentities] PRIMARY KEY CLUSTERED 
(
    [intTableId] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF,  ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

および挿入トリガー:

-- INSERT --
IF OBJECT_ID ('dbo.trgtblsysTrackerMessagesIdentity', 'TR') IS NOT NULL
   DROP TRIGGER dbo.trgtblsysTrackerMessagesIdentity;
GO
CREATE TRIGGER trgtblsysTrackerMessagesIdentity
ON dbo.tblsysTrackerMessages
INSTEAD OF INSERT AS 
BEGIN
    DECLARE @intTrackerMessageId INT
    DECLARE @intRowCount INT

    SET @intRowCount = (SELECT COUNT(*) FROM INSERTED)

    SET @intTrackerMessageId = (SELECT intIdentityLast FROM tblsysIdentities WHERE intTableId=1)
    UPDATE tblsysIdentities SET intIdentityLast = @intTrackerMessageId + @intRowCount WHERE intTableId=1

    INSERT INTO tblsysTrackerMessages( 
    [intTrackerMessageId],
    [intTrackerId],
    [strMessage],
    [intTrackerMessageTypeId],
    [datCreated],
    [strCreatedBy])
    SELECT @intTrackerMessageId + ROW_NUMBER() OVER (ORDER BY [datCreated]) AS [intTrackerMessageId], 
    [intTrackerId],
   [strMessage],
   [intTrackerMessageTypeId],
   [datCreated],
   [strCreatedBy] FROM INSERTED;

   SELECT TOP 1 @intTrackerMessageId + @intRowCount FROM INSERTED;
END