130

SQLServer2012データベースのautoidentityint列が正しくインクリメントされないという奇妙なシナリオがあります。

主キーとしてint自動IDを使用するテーブルがあり、それが散発的に増分をスキップしているとします。次に例を示します。

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

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

これはどのように起こっていますか?それを止める方法はありますか?

4

3 に答える 3

81

これはすべて完全に正常です。Microsoftsequencesは SQL Server 2012 に追加しました。最終的に、ID キーの生成方法を追加および変更する可能性があります。いくつかの説明については、こちらをご覧ください。

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

  1. トレース フラグ 272 を使用します。これにより、生成された ID 値ごとにログ レコードが生成されます。このトレース フラグをオンにすると、ID 生成のパフォーマンスが影響を受ける場合があります。
  2. NO CACHE 設定でシーケンス ジェネレーターを使用する ( http://msdn.microsoft.com/en-us/library/ff878091.aspx )
于 2013-01-04T18:29:22.503 に答える
4

同じ問題が発生し、SQL Server 2012 で次のバグ レポートが見つかりました。それでも問題が発生する条件を参照してください。いくつかの回避策があります (ただし、試していません)。 フェールオーバーまたは再起動により ID が再シードされる

于 2014-01-23T13:01:45.730 に答える
1

トレース フラグ 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
于 2015-05-04T13:38:57.050 に答える