Merge Replication - Manual Range Handling

,

Introduction

For normal transactional and snapshot replication, an existing identity

property on a published table is not transferred to the subscriber. This is

simply because it would never be required, as the subscriber is not intended to

insert rows him/herself. Merge replication however is intended for independent,

disconnected access to data, so in this case the identity property is

transferred. The question therefore is how to manage the identity ranges and

ensure there is no overlap in identity values on synchronization. Basically,

there are 2 options - automatic and manual range management. SQL Server can

automatically manage identity ranges in merge replication but this has a

reputation for sometimes becoming problematic. Although it is true that when the

range runs out before synchronization takes place there can be complications, in

most cases this can be simply avoided: typically the identity attribute applies

to an integer datatype, and as these can range from -2,147,483,648

through 2,147,483,647 then really unless you have an incredibly big number of

subscribers, selecting a large range of values per subscriber should ensure that

there is never any need for a range to run out. Nevertheless, it is often a

question asked on newsgroups of how to manually administer the identity ranges

and so take the matter entirely into your own hands. This article explains

step-by-step how to practically implement such an algorithm.

(1) The NoSync Method

Firstly select the algorithm you'll use to ensure each node's range won't overlap. There

are several methods to chose from (see

Michael Hotek's site). For example, lets assume you have a publisher and 3

subscribers. The publisher can have positive even numbers, the first subscriber

positive odd numbers, the second subscriber negative even numbers and the third

subscriber negative odd numbers. Using this method, each node has roughly one

billion possible entries.

Once the algorithm is selected, make sure the seed (2)

and increment (2) are set correctly at the publisher before publishing the

table.

If you try to change the identity value later on at the

publisher or the subscriber this will result in the error message below. This

applies at the publisher as soon as the table is published,

even before there is a subscriber:

'tCompany' table

- Unable to modify table.

ODBC error: [Microsoft][ODBC SQL Server

Driver][SQL Server]Cannot drop the table 'dbo.tCompany' because it is being used

for replication.

Now publish the table using merge replication. Be sure

to leave the Identity Range checkbox on the article properties blank to allow

manual control of the identity range.

Next transfer the table to the subscriber. You can use

DTS, backup/restore, BCP, linked servers - whatever you find useful. The table

can only be transferred once it has a uniqueidentifier column having the rowguid

attribute, or you'll get the error below on synchronization:

Error: Invalid column name 'rowguidcol'.

As long as the order in this article is followed, this

error can't occur, as either the table already has the rowguid. or publishing

the table will add one to the table.

Next, on the subscriber reset the current identity

value and the seed. Why is this necessary? Consider the case if there are 4

records:

ID Company rowguid
1 HP {5B9D38B2-5089-4C42-816B-48D0157ADA34}
2 DH {5A17C1B2-C045-4279-87BE-38F5F4959C0B}
3 IBM {B2FF82DA-5384-42AF-92F0-4029A5908395}
4 Microsoft {AB637574-7EBF-4950-9865-5378166BEB96}

If the publisher has a seed = 2 and increment = 2 and the first

subscriber has seed = 1 and increment = 2, in either case the next record will

have an ID of 6. This is because the current identity value is 4 so in both

cases the next value is 4 + 2. So,

DBCC CHECKIDENT (tCompany,RESEED, 5) 

needs to be run on the subscriber to start things off correctly. This

could be done using a post-snapshot script, but as the seed and increment must

be changed manually then having one extra manual step is the easiest solution.

Actually this step can be done on its own, and the seed

and increment on the subscriber left the same as that on the publisher i.e. in

this example the identity value is going up in twos, so resetting the current

identity value is sufficient. However this can be a little confusing from the

administration point of view and it's preferable later on to be able to have a

look at the seed and increment settings on a table to determine the intended

demarcation.

Finally do a nosync initialization. If you're doing this through scripts

this is sp_addsubscription

with @sync_type=none, or through the GUI select the option

below.

As with any merge nosync initialization, there is a

price to pay - any other articles added must also be nosync ones. With this in

mind, you might want to isolate this article, and any associated ones into their

own publication.

(2)Using @creation_script in sp_addmergearticle

The second method is not

fully supported by the GUI. It involves defining a separate script to create the

table on the subscriber

exec sp_addmergearticle @publication = N'TestIdentitiesXXX', @article = N'tCompany', @source_owner = 
N'dbo', @source_object = N'tCompany', @type = N'table', @description = null, @column_tracking
= N'true', @pre_creation_cmd = N'drop', @creation_script = 'C:\misc\tCompany.sql',
@schema_option = 0x00, @article_resolver = null, @subset_filterclause =
null, @vertical_partition = N'false', @destination_owner = N'dbo', @auto_identity_range
= N'false', @verify_resolver_signature = 0, @allow_interactive_resolver =
N'false', @fast_multicol_updateproc = N'true', @check_permissions = 0

The arguments are much as

per usual, with the exception of @creation_script which defines the file used to

create the table, and the @schema_option which forces the aforementioned file to be used. The script

itself (C:\misc\tCompany.sql) is a simple create table script generated by

enterprise manager on the publisher, but with the identity seed altered relative

to the publisher:

[ID] [int] IDENTITY (2, 2) NOT FOR REPLICATION NOT NULL

Once again, after

initialization the current identity value will need altering to reseed the

starting point.

After the snapshot agent

has run, the text file is transferred to the repldata share. This file can be

edited by hand to modify the identity attributes before each subscriber

initializes. Such changes can theoretically be made using a system stored

procedure to make changes to an existing article's details -

sp_changemergearticle. However, once one subscriber has synchronized, changing

the creation script using this method will invalidate this subscription and

you'll be obliged to reinitialize all other subscribers (@force_invalidate_snapshot

= 1 and @force_reinit_subscription = 1) so in practice the file can only be

altered manually.

Any further articles can

be added to this publication as per usual.

Conclusions

Two alternative methods

are presented to allow manual identity range management. The first is easier to

set up using graphical tools than the second. However the second method allows

for more flexible addition of new articles to an existing publication.

Paul Ibison, December 2004, http://ssisblog.replicationanswers.com/

Rate

5 (2)

Share

Share

Rate

5 (2)