Question

I have migrated a series of tables from an SQL Server 2008 to a new SQL Server 2012 machine via Transactional Replication. That works fine so far and I also replicated indexes and default values to ensure the replicated data is equal to the original one.

When I detach the new machine from replication to act standalone as a replacement of the old machine, SQL Server starts filling up all the gaps in my identity columns which may cause different troubles. I.e. my code can't rely on having the highest ID for the last inserted line anymore. Also previously deleted user-IDs are recycled which may cause confusion at users side too.

Is there a way to make the new instance of my DB acting exactly like the old replicated one? In my experience, a running instance of a database never fills up gaps of previously deleted rows.

Was it helpful?

Solution

I have never seen this either. However it could be that the table gets reseeded to 0 when it gets deployed. Observe this example:

SET NOCOUNT ON;
GO
CREATE TABLE dbo.fooblat(id INT IDENTITY(1,1));
GO
INSERT dbo.fooblat DEFAULT VALUES;
GO 3
DELETE dbo.fooblat WHERE id = 2;
GO
DBCC CHECKIDENT('dbo.fooblat', RESEED, 0);
GO
INSERT dbo.fooblat DEFAULT VALUES;
GO 3
SELECT id FROM dbo.fooblat ORDER BY id;
GO
DROP TABLE dbo.fooblat;

Results:

id
----
1
1
2
3
3

Now, if the identity column is also primary key or otherwise unique, this same operation could still fill in the gaps, only the duplicate violations would fail. So repeating again with this table definition:

CREATE TABLE dbo.fooblat(id INT IDENTITY(1,1) PRIMARY KEY);
GO

Yields this (the first successful insert filled the gap):

id
----
1
2
3

Msg 2627, Level 14, State 1, Line 1
Violation of PRIMARY KEY constraint 'PK_fooblat_3213E83F6BF0A0C6'. Cannot insert duplicate key in object 'dbo.fooblat'. The duplicate key value is (1).
Msg 2627, Level 14, State 1, Line 1
Violation of PRIMARY KEY constraint 'PK_fooblat_3213E83F6BF0A0C6'. Cannot insert duplicate key in object 'dbo.fooblat'. The duplicate key value is (3).

You can avoid this situation by ensuring that the table is seeded correctly when it is put on the other system. This may just mean using a more reliable deployment technique, or it may mean - after populating and before letting any users in - you do something like this:

DECLARE @i INT, @sql NVARCHAR(MAX);
SELECT @i = MAX(id) FROM dbo.fooblat;
SET @sql = N'DBCC CHECKIDENT(''dbo.fooblat'', RESEED, ' + RTRIM(@i) + ');';
EXEC sp_executesql @sql;
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top