首页 > 数据库 >SQL Server自增列跳号总结

SQL Server自增列跳号总结

时间:2024-03-08 16:44:17浏览次数:34  
标签:CACHE Server SQL 增列 IDENTITY 1000

从SQL Server 2012开始,Microsoft就引入了一个新的功能/特性IDENTITY CACHE,引入这个功能的目录是为了提高包含自增列(IDENTITY)相关表的INSERT性能。但是随之而来的,就是可能会出现自增列(标识列)的跳号问题,如下所示:

CREATE TABLE TEST(ID INT IDENTITY(1,1), NAME VARCHAR(16));

INSERT INTO TEST(NAME)
SELECT 'Kerry1' UNION ALL
SELECT 'Kerry2';

SELECT * FROM TEST;

然后,我们通过Windows任务管理器,杀掉SQL Server服务的进程,模拟SQL Server Abort或服务器意外重新启动的情况。或者你使用下面命令关闭数据库实例

SHUTDOWN WITH NOWAIT

我们重启数据库实例后,继续插入数据,你会发现字段ID跳号了,如下截图所示:

INSERT INTO TEST(NAME)
SELECT 'Kerry3';

自增列跳号的差值(GAP)

从上面的测试实验,我们看到自增列ID的跳号的差值(GAP)为1000,那么有一个疑问,所有的自增列跳号的差值(GAP)都是1000吗? 答案是No,这个跳号的差值(GAP)跟自增列的数据类型有关,如果自增列字段类型为INT类型的话,差值(GAP)为1000,如果自增列为BIGINT或Numeric数据类型的话,跳号(GAP)为10000,这个有兴趣的话,可以自行测试一下。这里就不展开叙述了。

另外,生产环境自增列跳号的值有可能小于1000或10000,不一定完全是1000或10000,你可以模拟这种情况,如下所示,在测试环境循环插入数据,然后模拟异常重启。

DECLARE @insert_rows INT =0
DECLARE @row_count INT=100000

WHILE @insert_rows < @row_count
BEGIN
INSERT INTO TEST(NAME)
SELECT 'KADFADFIAT'

 SET @insert_rows =@insert_rows+1
END;

因为官方文档缺少相关资料,对其内部原理所知甚少,所以很难准确描述为什么跳号会小于1000或10000,我们只需知道有这种现象。我曾绞尽脑汁设想一些可能性,但是都缺乏证据支持。

什么时候出现自增列跳号?

什么场景会出现自增列跳号呢? SQL Server 由于出于性能原因而缓存自增列的值,在数据库故障或服务器重新启动期间,一些分配的值可能丢失。 这可能导致在插入时自增列值(标识值)之间有间隔。具体来说,分为下面几种情况:

  • 1: SQL Server奔溃或服务器意外重启(例如,服务器宕机、蓝屏、SQL Server实例Crash、SHUTDOWN WITH NOWAIT)
  • 2: AlwaysON的故障转移时出现自增列跳号。如果正常的重启SQL Server服务/实例是不会导致自增列跳号的。至于原因和内部原理,没有相关的官方解释,但是参考ORACLE SEQUENCE跳号总结[1],大体原理估计也差不多。

如何禁止自增列跳号

1:跟踪标记禁用IDENTITY CACHE

在早期的SQL Server版本,例如,SQL Server 2012、2014等版本,由于一些业务逻辑的要求,你要杜绝/禁止自增列跳号的话,必须通过跟踪标记272来禁用IDENTITY CACHE,避免在服务器意外重新启动(Abort/宕机)或故障转移到辅助服务器的情况下,禁用自增列预分配以避免标识列的值出现跳号的情况,这个是在全局/实服务器级别设置。如下所示:

2:使用序列替换自增列

如果不允许有间隔,应用程序应使用自己的机制来生成键值。使用没有CACHE的序列替换自增列。将序列生成器与 NOCACHE 选项结合使用可以限制从未提交的事务的间隔。

3:在数据库级别禁用IDENTITY CACHE

从SQL Server 2017开始,Micosoft提供提供了一个新功能,允许你在数据库级别禁用或启用标识缓存(IDENTITY CACHE)。如下所示

USE <YourSQLDB>
GO
ALTER DATABASE SCOPED CONFIGURATION SET IDENTITY_CACHE = ON
GO

切换到指定的数据库,执行下面第二条SQL就能开启IDENTITY CACHE,如果想关闭数据库的IDENTITY CACHE功能的话,就执行下面SQL

USE <YourSQLDba>
GO
ALTER DATABASE SCOPED CONFIGURATION SET IDENTITY_CACHE = OFF
GO

查询开启还是关闭了IDENTITY CACHE,可以通过下面语句查看

USE <YourSQLDba>
GO
SELECT * FROM sys.database_scoped_configurations WHERE NAME='IDENTITY_CACHE'

参考资料

[1]

1: https://www.cnblogs.com/kerrycode/p/7461180.html

标签:CACHE,Server,SQL,增列,IDENTITY,1000
From: https://www.cnblogs.com/kerrycode/p/18061330

相关文章

  • MySQL(二):MySQL中的系统库
    1、概述MySQL有几个系统数据库,包含了MySQL服务器运行过程中所需的一些信息以及一些运行状态信息。系统库作用performance_schemaMySQL服务器运行过程中的一些状态信息,是对MySQL服务器的一个性能监控,包括最近执行的语句,及花费的时间、内存使用情况等信息informa......
  • MySQL(一):整体架构
    1、整体概述  MySQL是由连接池、管理工具和服务、SQL接口、解析器、优化器、缓存、存储引擎、文件系统组成。1.1、ConnectionPool-连接池创建数据库连接是一个耗时的操作,连接池的作用就是将这些连接缓存下来,再次访问数据库时,可以直接用已经建立好的连接,提升服......
  • windows搭建rails环境中,mysql2 gem 安装error问题
    windows搭建rails环境中,mysql2gem安装error问题可以尝试使用下面几种方法:1. Uninstallingandreinstallingthegemwilloftensolvethisissuewithnoneedtodownloadandmovefilesaroundbyhand.Fromyourrailsappdirectory:>gemuninstallmysql2You......
  • docker 部署 django + mysql + vue 项目
    ​项目目录结构,在Vue和Django项目根目录下创建Dockerfile文件,在父级目录下创建docker-compose.yml文件Project#父级目录├─client#vue3项目目录│├─public│└─src│├─*files│├─*files│├─Dockerfile└─server#Django项......
  • mysql 导入的文件大小限制
    本文为joshua317原创文章,转载请注明:转载自joshua317博客 https://www.joshua317.com/article/323MySQL是一种流行的关系型数据库管理系统,支持导入各种类型的数据文件。然而,在导入文件时,可能会遇到文件大小的限制问题。默认情况下,MySQL的导入文件大小限制为1GB。这是通过m......
  • Archery SQL 审核查询平台
     ArcherySQL审核查询平台 archer Archery项目是基于archer二次开发而来goInception 一个集审核、执行、备份及生成回滚语句于一身的MySQL运维工具JetBrainsOpenSource 为项目提供免费的IDE授权......
  • mysql 按条件排序:order by 高级用法之case when, if 复杂排序
    转载自:https://blog.csdn.net/weixin_44684303/article/details/124445293实例1原始数据顺序需要的效果:学科按照顺序语文,数学,英语分数倒序演示创建表CREATETABLE`student_score`(`id`bigint(20)NOTNULLAUTO_INCREMENTCOMMENT'主键',`student_i......
  • Mysql数据备份
    一、数据库备份1、备份可分为完全备份、差异备份、增量备份2、常见备份方法:物理备份:冷备份,在数据库关闭状态下进行备份启用二进制日志进行增量备份:二进制日志为用户提供复制、对执行备份点后进行的数据库更改所需的信息进行备份。二、备份操作1、完全备份1、直接打包数......
  • MYSQL学习笔记4: DML数据操作(增删改)
    DML数据操作(增删改)INSERT插入给指定字段插入数据insertinto表名(字段1,字段2...)values(值1,值2);向itcast的worker表的制定字段中插入一条新数据insertintoworkers(id,workNo,name,gender,age,idCard,entryDate)values(1,'1','hikari39','女',2......
  • MYSQL学习笔记3: DDL表修改
    DDL表修改在表中添加新字段#格式ALTERTABLE表名ADD字段名(长度)[COMMENT注释][约束];#在itcast表中新建一个nickname字段altertableitcastaddnicknamevarchar(20)comment'昵称';修改字段数据类型altertable表名modify字段名新数据类型(长度);修改字段名......