没有 RESEED 的 MSSQL 身份插入
Posted
技术标签:
【中文标题】没有 RESEED 的 MSSQL 身份插入【英文标题】:MSSQL Identity Insert without RESEED 【发布时间】:2021-09-14 06:36:47 【问题描述】:我在 4 个不同的位置有 4 个数据库。我写了一个程序来互相同步。该程序最多可在 2 个位置正常工作。我会解释原因。
每个数据库都有每个表的身份主键。如果我只配置了两个数据库。我可以将第一个数据库的身份设置为 IDENTITY(1,1),将另一个数据库设置为 IDENTITY(-1,-1)。但是如果有多个位置,那么我将不得不为每个数据库遵循一些模式。喜欢,
1st - Identity(1,5)
2nd - Identity(2,5)
3rd - Identity(3,5)
........
........
现在我的问题是,当我在每个数据库之间同步数据时。我使用 IDENTITY_INSERT ON 关键字。在 INSERTING 行到另一个数据库后,SEED 值将变为 MAX,它将打破这种模式。
例如,数据库 A 有这样的值,
1
6
11
16
数据库 B 有值,
2
7
12
17
如果我将数据从数据库 B 同步到 A。它(A)将 SEED 为 17,下一个值为 22。此时模式将中断。
有人在其他论坛上问过同样的问题。链接在这里。 https://www.sqlservercentral.com/forums/topic/identity-insert-without-reseed/page/2 但是解决方案对我不起作用。他们建议使用“REPLICATION=TRUE;”在连接字符串中以避免 RESEED 但这对我不起作用。
如何解决这个问题?我想我可以通过为每个数据库分配范围来做到这一点,但我更愿意使用序列号。
谢谢。
【问题讨论】:
这就是微软创建复制服务的原因。它会为您处理所有这些。 使用 GUID 或使用包含系统 ID 的复合键。无论您想出什么编号系统,都会发生冲突或编号用完 【参考方案1】:如果您有多个带有标识列的服务器,并且您希望将数据合并到一个地方,那么 SQL Server 提供了多种复制和分发的可能性。
如果我理解您的问题,那么您可以将服务器设置为使用不同的值范围。一种方法是在每台服务器上将标识列启动为不同的值:
identity(1, 1)
identity(1000000, 1)
这假设您在每台服务器上的行数永远不会超过 1000000。
一种稍微不同的方法是将偶数放在一台服务器上,将奇数放在另一台服务器上:
identity(1, 2)
identity(2, 2)
这两者都保证了“合并”后身份值不会冲突。
【讨论】:
感谢您的回复。您已经很好地理解了我的问题。我想参考您提到的第二种方法,但存在一些问题。当我使用 SET IDENTITY_INSERT ON 插入任何行时。然后模式将打破。 SEED 值将重置为最高值。 我再次检查了这个。当它从一个同步到另一个时。奇数和偶数将不再起作用。【参考方案2】:...将标识列标记为“不用于复制”
ssms tab_1(正常连接):
use tempdb
go
drop table if exists dbo.x;
drop table if exists dbo.y;
go
create table dbo.x(id int identity(1,5), a char(1) default('a'));
create table dbo.y(id int identity(1,5) not for replication, a char(1) default('a'));
go
insert into dbo.x(a)
values ('a'), ('a'), ('a');
insert into dbo.y(a)
values ('a'), ('a'), ('a');
go
select 'x' as tbl, * from dbo.x;
select 'y' as tbl, * from dbo.y;
go
ssms tab_2 (..Options-->附加连接参数--> add Replication=true;) :
set identity_insert dbo.x on;
insert into dbo.x(id, a)
output inserted.*
values (12, 'b');
set identity_insert dbo.x off;
select 'x' as tbl, * from dbo.x;
go
set identity_insert dbo.y on; --..not actually needed
insert into dbo.y(id, a)
output inserted.*
values (12, 'b');
set identity_insert dbo.y off; --..
select 'y' as tbl, * from dbo.y;
go
/*
--error for a "typical" insertion when in "Replication"
--:Explicit value must be specified for identity column in table 'y' either when IDENTITY_INSERT is set to ON
-- or when a replication user is inserting into a NOT FOR REPLICATION identity column.
insert into dbo.y(a)
values ('a')
*/
ssms tab_3(正常连接):
insert into dbo.x(a)
values('z'), ('z');
go
insert into dbo.y(a)
values('z'), ('z');
go
select 'x' as tbl, * from dbo.x;
select 'y' as tbl, * from dbo.y;
go
【讨论】:
以上是关于没有 RESEED 的 MSSQL 身份插入的主要内容,如果未能解决你的问题,请参考以下文章
远程连接到 MSSQL,使用 Windows 身份验证,JAVA