You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PC崩溃后SQL Server主键ID异常跳增的问题及处理方案咨询

问题分析与解决方案

一、ID跳变到1004的根源

这是SQL Server IDENTITY(自增列)的默认缓存机制导致的:

  • SQL Server为提升性能,会预分配一批自增值(默认缓存大小为1000)存储在内存中,每次插入时直接从缓存取号。
  • 断电时,内存中未使用的缓存值会丢失,重启后数据库会从上次缓存的起始值 + 缓存大小开始分配新ID。比如你之前的最后一条ID是4,缓存预分配了1-1004的范围,断电后未使用的5-1003丢失,下次就从1004开始,这就是两次断电都跳到1004的原因。
  • SSMS运行与此无关,它只是客户端工具,不会干预数据库引擎的自增缓存逻辑。

二、保障主键ID完整性的方案

这里的「完整性」需要分两种场景讨论:

1. 场景:业务要求ID连续无跳号(如发票号、单据号)

如果必须保证ID连续,可通过以下方式禁用缓存:

  • 数据库级关闭IDENTITY缓存:
    ALTER DATABASE [你的数据库名] SET IDENTITY_CACHE OFF;
    
    该设置会让所有表的IDENTITY列每次生成新ID时都写入系统表,断电后不会丢失未使用的ID,但会牺牲一定性能(每次插入都要磁盘IO)。
  • 使用无缓存的序列(SEQUENCE):
    替代IDENTITY,创建序列时指定NO CACHE:
    CREATE SEQUENCE dbo.TableIdSequence
      AS INT
      START WITH 1
      INCREMENT BY 1
      NO CACHE;
    
    插入数据时调用序列取号:
    INSERT INTO 你的表 (Id, ...)
    VALUES (NEXT VALUE FOR dbo.TableIdSequence, ...);
    
    序列的NO CACHE会让每次取值都持久化到磁盘,避免跳号,同样存在性能损耗。

2. 场景:仅需ID唯一(大多数业务场景)

如果业务只要求主键唯一,不需要连续,完全不需要修改现有方案:

  • IDENTITY的跳号是正常设计,不会导致数据冲突,也不影响数据完整性。客户环境中即使出现断电跳号,只会让ID不连续,但每个ID仍然唯一,对业务逻辑无影响。
  • 这种情况下,IDENTITY是最优选择,性能远高于GUID或无缓存序列。

三、关于GUID的取舍

GUID适合分布式系统(多实例数据库需要全局唯一ID),但单实例数据库中没必要用:

  • 如果必须使用GUID,用NEWSEQUENTIALID()替代NEWID():
    CREATE TABLE 你的表 (
      Id UNIQUEIDENTIFIER DEFAULT NEWSEQUENTIALID() PRIMARY KEY,
      ...
    );
    
    NEWSEQUENTIALID()生成的是顺序GUID,能大幅减少索引碎片,性能比随机GUID好很多,但仍不如INT/BIGINT的IDENTITY高效(GUID占用16字节,INT仅4字节,索引维护成本更高)。

四、最佳处理方式

  1. 先确认业务需求:如果不是必须要求ID连续,保留IDENTITY即可,跳号不影响数据。
  2. 如果必须连续,优先选择数据库级关闭IDENTITY缓存(比序列更贴合原有IDENTITY使用习惯),同时评估性能影响。
  3. 除非是分布式场景,否则不推荐使用GUID作为主键,避免不必要的性能损耗。

内容的提问来源于stack exchange,提问作者GoodWorld113

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 18:40:32