none
请教关于SQL2012 AlwaysOn在故障转移时预留的标识列的问题 RRS feed

  • 问题

  • 现有1个应用,会使用标识列的最后3位,作为流水号,前面加上日期,作为单号,存入数据库中(因每日该表单不会超过999笔)

    在未使用AlwaysOn之前,并未出现单号重复的情况,改用AlwaysOn之后,发现出现单号重复的情况

    经查,发现AlwaysOn集群,在进行故障转移时,会预留(占用)900-1000范围内的标识列,且预留数量并不固定

    举例来说,原标识列使用到123500,此时发生故障转移,有900多个标识列被预留,故障转移完成后,标识列从124456开始,由于程序截取了最后3位,123456和124456的流水号都是456,就会造成单号重复的情况,如果1天内多次出现故障转移,就会出现多个重复的单号

    现请问,能否手动设置这部分预留的标识列的数量?

    比如上例中,我设置为1000,则该问题就能得到解决

    PS:目前无法修改客户端

    麻烦移到SQL区,谢谢
    2014年7月3日 7:34

答案

  • 这个应该没办法, 这个是 rollback 导致的, 故障转移的时候, 一些没有完成的事务会回滚, 对于标识列而言, 标识值的分配不受事务回滚的影响

    这就导致已经分配, 但由于事务回滚, 并没有存储到表中使用的这系列标识值不会被使用, 出现楼主所描述的保留现象

    2014年7月7日 8:52
  • create table #t(id int identity, c1 int)
    begin tran
    	insert #t values(0)
    	insert #t values(0)
    rollback
    insert #t values(0)
    select * from #t	-- 这里面看到一条记录, 自增列值是3, 表明数据操作回滚了, 标识值分配并没有回滚
    drop table #t
    

    2014年7月7日 8:53

全部回复

  • You should reseed identity column with 'dbcc checkident' after swing db.
    2014年7月7日 3:30
  • You should reseed identity column with 'dbcc checkident' after swing db.

    可以设置在故障转移后自动运行吗?

    毕竟无法预判什么时候会发生故障转移,也不可能在发生后第一时间发现

    唯一能处理的,也就是有计划的手动故障转移,比如要重启某个节点的时候,但也很难保证能在切换过去后第一时间更改标识

    2014年7月7日 8:15
  • 这个应该没办法, 这个是 rollback 导致的, 故障转移的时候, 一些没有完成的事务会回滚, 对于标识列而言, 标识值的分配不受事务回滚的影响

    这就导致已经分配, 但由于事务回滚, 并没有存储到表中使用的这系列标识值不会被使用, 出现楼主所描述的保留现象

    2014年7月7日 8:52
  • create table #t(id int identity, c1 int)
    begin tran
    	insert #t values(0)
    	insert #t values(0)
    rollback
    insert #t values(0)
    select * from #t	-- 这里面看到一条记录, 自增列值是3, 表明数据操作回滚了, 标识值分配并没有回滚
    drop table #t
    

    2014年7月7日 8:53
  • 如果你的程序可以控制, 则可以考虑为流水号列设置唯一性约束(或者唯一索引), 程序插入的时候如果出现重复, 则插入失败, 程序检查到失败去做一个重置标识列的操作
    2014年7月7日 9:02