【问题标题】:Odd SQL Server 2012 IDENTITY issue奇怪的 SQL Server 2012 IDENTITY 问题
【发布时间】:2012-12-01 07:40:05
【问题描述】:

我以前从未见过这种情况,很奇怪。

我有一个正在开发的本地 SQL Server 2012 Express 数据库。使用 TestDrive 插件运行一套简单的测试并使用 EF v5 访问数据库。

我刚刚运行了一个将记录插入数据库的测试。我在表中有 9 行从 id 1-9 开始。下一次插入,ID 正好跳了 10000 !!!!

Id 列显示:

1, 2, 3, 4, 5, 6, 7, 8, 9, 10009

我知道失败的插入也会增加 ID,但我可以保证 10,000 在测试运行之间的 5 秒内没有插入失败...

表结构非常简单,一堆列和一个自动递增,bigint(长)类型的标识列,没有 SP、触发器或任何其他程序化内容。

[Id] [bigint] IDENTITY(1,1) NOT NULL,

很困惑,有没有其他人看到过这种情况?

【问题讨论】:

  • 我看不出它怎么会是我的代码。该代码对 ID 没有任何作用,它是一个 INSERT 命令,而不是 UPDATE 命令,如果 INSERT 尝试应用一个 ID,它只会忽略 ID 值...
  • 似乎这可能是 2012 年的一个错误,因为它也被其他人报告在这里...connect.microsoft.com/SQLServer/feedback/details/743300/…我刚刚为此添加了一个日志...
  • 好像是SQL引擎重启引起的……但是为什么我的种子为1时它会跳10000有点疯狂……
  • 这是一个已知问题。不幸的是,MS没有注意。这个问题让我们非常头疼。

标签: sql entity-framework sql-server-2012-express


【解决方案1】:

这个blog post 有一些额外的细节。看起来在 2012 年,identity 被实现为一个序列。默认情况下,一个序列有一个缓存。如果缓存丢失,您将丢失缓存中的序列值。

建议的解决方案是使用no cache 创建一个序列:

CREATE SEQUENCE TEST_Sequence
    AS INT
    START WITH 1
    INCREMENT BY 1
    NO CACHE

据我所知,标识列后面的序列是不可见的。你不能改变它的属性来禁用缓存。

要将其与 Entity Framework 一起使用,您可以将主键的 StoredGeneratedPattern 设置为 Computed。然后您可以在instead of insert 触发器中生成身份服务器端:

if exists (select * from sys.sequences where name = 'Sequence1')
    drop sequence Sequence1
if exists (select * from sys.tables where name = 'Table1')
    drop table Table1
if exists (select * from sys.triggers where name = 'Trigger1')
    drop trigger Trigger1
go
create sequence Sequence1
    as int
    start with 1
    increment by 1
    no cache
go
create table Table1
    (
    id int primary key,
    col1 varchar(50)
    )
go
create trigger Trigger1
    on Table1
    instead of insert
as
insert  Table1
        (ID, col1)
select  next value for Sequence1
,       col1
from    inserted
go
insert Table1 (col1) values ('row1');
insert Table1 (col1) values ('row2');
insert Table1 (col1) values ('row3');

select  * 
from    Table1

如果你找到更好的解决方案,请告诉我:)

【讨论】:

  • 啊……这很有趣。我会看看我是否可以让这种无缓存方法与 EF 一起使用......
  • 嗯......这一切对我来说看起来有点乱 :( 我会看看我能不能找到任何关于它的东西并报告回来
  • 其实你知道的。我什至不确定我是否在乎,这是一个 bigint,所以我不会很快用完。我的 ID 不会以任何方式使用,这取决于它们的创建方式,并且如果它只在 SQLServer 在生产中重新启动时发生,这种情况不会经常发生(著名的遗言!)......至少我现在不担心,很可能会回到 2008 R2 进行真正的生产部署......
  • 同意。只有当身份绝对必须是连续的时,我才会调整这么远。
【解决方案2】:

如果您在每次插入查询后调用“检查点”命令,它将解决您的问题。

更多信息请阅读SQL Server中的Checkpoint

【讨论】:

  • 数据库中有大约 300 个插入查询。这是行不通的。 MS 需要解决这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多