亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定

SQL Server identity range check報錯解決

標簽:
SQL Server

    最近帮一个客户搭建跨洋的合并复制,由于数据库非常大,跨洋网络条件不稳定,因此只能通过备份初始化,在初始化完成后向海外订阅端插入数据时发现报出如下错误:

Msg 548, Level 16, State 2, Line 2  
The insert failed. It conflicted with an identity range check constraint in database %s, replicated table %s, column %s. If the identity column is automatically managed by replication, update the range as follows: for the Publisher, execute sp_adjustpublisheridentityrange; for the Subscriber, run the Distribution Agent or the Merge Agent.

 

原因?

    在SQL Server中,对于自增列的定义是对于每一条新插入的行,都会自动按照顺序新生成一个递增的数字,改数字通常和业务无关且被用于作为主键。但如果该表用于可更新事务复制或者合并复制,那么该自增列的区间范围则由复制管理。

    此时,复制可以保证自增列可控,因为复制代理插入行时不会导致自增列自增,只有用户显式插入时才会导致自增列自增。

    让我们来做一个实验。首先创建表,表定义如下:

CREATE TABLE [dbo].[Table_1](
    [c1] [int] IDENTITY(1,1),
    [c2] [int] NULL,
    [ROWGUID] [uniqueidentifier] NOT NULL,
    [rowguid4] [uniqueidentifier] ROWGUIDCOL  NOT NULL,
 CONSTRAINT [PK_Table_1] PRIMARY KEY CLUSTERED 
(
    [c1] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

    此时我们对创建合并复制,并把该表包含在内,并使用快照代理初始化复制,当完成该步骤时,我们发现该表上自动多了两个约束,如图1所示。

https://img1.sycdn.imooc.com//5acc7980000120c611100367.jpg

    

     我们看到该约束的定义只允许4002到5002以及5002到6002之间的数据被插入。

     此时如果出现了一些BUG或者人为改动了该表自增列种子的值,则会报错,如图2所示。

https://img1.sycdn.imooc.com//5acc79890001c58106660251.jpg

    该约束会由合并代理自动递增,比如说我们用如下代码插入2000条数据,则发现该约束会自动递增如图3所示。

DECLARE @index INT=1
WHILE @index<2000
BEGIN
INSERT INTO table_1(c2,ROWGUID) VALUES(2,NEWID())
SET @index=@index+1
END

 https://img1.sycdn.imooc.com//5acc79a70001bac208860107.jpg

解决办法  

    此时我已经找出了上面报错的原因,因为是由于从备份初始化,那么备份以及备份传输期间发布库又有新的数据插入,此时发布库比如说,该表的种子大小已经增加到了6000,而备份中该表大小还是5000,而约束已经滑动到了6000,那么在订阅端插入数据时就会发生这种问题。

解决办法1

    在发布端使用sp_adjustpublisheridentityrange 存储过程使得约束范围自动向后滑动,比如从6000-8000滑动到8000-10000。缺点自增值之间会有一个GAP。如果业务允许,推荐使用该做法。

    sp_adjustpublisheridentityrange @table_name=’表名称‘

解决办法2

    在发布端运行SELECT  IDENT_CURRENT('表名称'),找到发布表的种子值。在订阅端通过DBCC CHECKIDENT (表名称,RESEED, 设置为上面值)命令将两端种子值设置为一致。

解决办法3

    在订阅端运行合并代理,即可修复数据。如果此方法不行,则再次尝试上述方法。

解决办法4

    不用自增列,而使用GUID列,但这涉及到表结构以及程序的修改,而且需要重新初始化复制,因此不是每一个环境都有条件这么做就可以正常插入数据了。

點擊查看更多內容
TA 點贊

若覺得本文不錯,就分享一下吧!

評論

作者其他優質文章

正在加載中
  • 推薦
  • 評論
  • 收藏
  • 共同學習,寫下你的評論
感謝您的支持,我會繼續努力的~
掃碼打賞,你說多少就多少
贊賞金額會直接到老師賬戶
支付方式
打開微信掃一掃,即可進行掃碼打賞哦
今天注冊有機會得

100積分直接送

付費專欄免費學

大額優惠券免費領

立即參與 放棄機會
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號

舉報

0/150
提交
取消