首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Windows Azure SQL数据库-标识自动增量列跳过值

Windows Azure SQL数据库-标识自动增量列跳过值
EN

Stack Overflow用户
提问于 2013-06-10 01:35:08
回答 4查看 7.1K关注 0票数 17

目前正在使用Entity Framework5开发ASP.Net MVC4应用程序。在初始开发阶段使用CodeFirst。但是现在已经禁用了自动迁移和直接使用SSMS和编写POCO来设计新表。一切都运行良好。

最近,在生产中发现了一个奇怪的问题。其中一个初始设计表中的记录跳过了超过900个数字的自动递增标识值。在过去的3个月里,这种情况已经发生了3次。已在本地调试应用程序,但无法重现。没有观察到任何模式或趋势。

模型:

代码语言:javascript
复制
public class Enquiry
{
    [Key]
    [DatabaseGeneratedAttribute(DatabaseGeneratedOption.Identity)]
    public Int64 EnquiryId { get; set; }

    [Required]
    public int UserId { get; set; }

    [Required]
    public byte Bid { get; set; }

    ...

    [Required]
    public DateTime Created { get; set; }

    [Required]
    public DateTime Modified { get; set; }
}

public class EnquiryDetail
{
    [Key]
    public Int64 EnquiryId { get; set; }

    [Required]
    public int CreditScore { get; set; }

    [Required]
    public byte BidMode { get; set; }

    public virtual Enquiry Enquiry { get; set; }
}

DBContext:

代码语言:javascript
复制
public class EscrowDb : DbContext
{

    public EscrowDb()
        : base("name=DefaultConnection")
    {

    }
    public DbSet<Enquiry> Enquiries { get; set; }
    public DbSet<EnquiryDetail> EnquiryDetails { get; set; }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
        modelBuilder.Entity<EnquiryDetail>()
            .HasRequired<Enquiry>(ed => ed.Enquiry)
            .WithRequiredDependent(e => e.EnquiryDetail);
    }
}

控制器:

代码语言:javascript
复制
[Authorize]
public class EnquiryController : Controller
{
    private EscrowDb _db = new EscrowDb();

    [HttpPost]
    [ValidateAntiForgeryToken]
    public ActionResult Create(EnquiryViewModel core)
    {
       var enquiry = new Enquiry();
       // Some code to set properties using passed ViewModel
       ...

       var enquiryDetail = new EnquiryDetail();
       // Some code to set properties using passed ViewModel
       ...

       enquiry.EnquiryDetail = enquiryDetail;

       _db.Enquiries.Add(enquiry);
       _db.SaveChanges();
    }
}

到目前为止,所有这些代码都工作得很好,除了identity值被几乎1000个数字的大间隙零星跳过。

有没有人遇到过这样的问题?请分享你的想法。

EN

回答 4

Stack Overflow用户

发布于 2013-07-10 22:00:07

如果您需要消除这些差距,那么在这里您可能就不走运了。

当我开发/测试一个新的应用程序时,我自己遇到了这个问题。根据我所读到的关于sql server 2012的内容,我对sql azure中正在发生的事情有了直观的认识。我还没有找到任何关于sql azure的文档。

根据我所读到的,这是一个被认为是错误的特性。在Sql server 2012中,Microsoft添加了创建序列的功能。序列记录了以1000为单位的块中使用的值。比方说你的序列在进行中。1,2,3,4,5...然后您的sql服务器将重新启动。好的,序列已经保存了块1-1000已经被使用的事实,所以它会跳到下一个1000……所以你的下一个值是1001,1002,1003,1004....这提高了使用序列时插入的性能,但可能会导致不寻常的间隙。对于您的序列,有一个解决方案。当指定你的序列时,添加"NOCACHE“参数,这样它就不会一次保存1000个块。See here for more documentation.

这成为一个问题的地方是,标识列似乎已经被更改为使用相同的范例。因此,当您的服务器重新启动时,或者在这种情况下,您的sql azure实例重新启动时,您的标识列中可能会出现很大的差距(1000),因为它会将大块缓存为“已用”。针对sql server 2012,有一个解决方案。您可以指定一个启动标志t272,以将您的身份还原为使用旧的sql server2008 r2范例。问题是我不知道(这可能是不可能的)如何在sql Azure中指定它。找不到文档。See this thread for more details on sql server 2012.

Check the documentation of identity here in the msdn.特别是“服务器重新启动或其他故障后的连续值”部分。这是它所说的:

服务器重新启动或其他故障后的

连续值由于性能原因,-SQL服务器可能会缓存标识值,并且某些分配的值可能会在数据库故障或服务器重新启动期间丢失。这可能会在插入时导致标识值出现间隙。如果间隙是不可接受的,那么应用程序应该使用带有NOCACHE选项的序列生成器,或者使用自己的机制来生成键值。

因此,如果您需要连续的值,可以尝试使用nocache指定一个序列,而不是依赖于您的标识列。我还没试过呢,but sounds like you'll have trouble getting this to work with entity framework.

抱歉,如果这不是很有帮助,但至少它是关于你所经历的一些信息。

票数 19
EN

Stack Overflow用户

发布于 2014-05-22 17:52:40

尝试使用带触发器的重新播种方法。我相信这应该可以解决这个问题,example of its use,并在该链接上看到更多的walkarounds。

代码语言:javascript
复制
USE [TEST]

CREATE TABLE TEST(ID INT IDENTITY(1,1),VAL VARCHAR(10))

CREATE TRIGGER TGR_TEST_IDENTITY ON TEST
FOR INSERT
AS
DECLARE @RESEEDVAL INT
SELECT @RESEEDVAL = MAX(ID) FROM TEST
DBCC CHECKIDENT('TEST', RESEED, @RESEEDVAL)

INSERT INTO TEST(VAL)VALUES('a')

SELECT * FROM TEST

由于'DBCC CHECKIDENT‘在Azure中不受支持,现在您可以使用此link中的方法,我得到了一些解决方法

  1. 在使用SqlAzure
  2. 的自动密钥时使用GUID作为密钥如果像我这样的整数密钥允许记录插入、返回、删除它并使用正确的密钥重新插入,方法是关闭identity并启用set identity_insert XXXTable -这基本上会关闭IDENTITY

然后,当我使用正确的键插入完成时,再次打开标识

set identity_insert XXXTable off --这基本上打开了身份

注意:对于正在接收大量insert请求的表,这不是一个很好的解决方案,但对于寻找临时解决方案的人来说可能很有用

票数 1
EN

Stack Overflow用户

发布于 2013-12-26 01:19:05

似乎没有针对SQL Azure的TF 272解决方案。在检查这两个表和检查插入的记录之前,我只是在两个表中注意到了这个问题(差距为999和1000),并认为这是一个安全漏洞。有关详细信息,请参阅this MS TechNet discussion的最后一项。有点让人放心,但看起来更像是一个bug而不是一个特性。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/17012339

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档