Average 28000 requests/month












  How to.......

Merge is hanging on initialization - what should I do?

There's loads of mentions of this recently so I should point out that the infinite loop that may occur on initialization is bypassed by using :

update sysmergepublications set generation_leveling_threshold = 0 (on the subscribers)

Is this supported? Interesting question as this solution came from the PSS folks. I suppose you'd have to open a support case with them and have them talk you through doing it for it to be supported. No hotfix as yet but I'll add an addendum when it comes in.
 


Is it possible to write conflict info to a separate (persistant) table?

You can use use perfmon to watch the conflicts per second counter of SQL Server:Replication Merge and run a job which reads the conflict tables when conflicts occur. You can also use sp_helpmergearticleconflicts and run it on the publisher and subscriber. It will return a list of articles with conflicts and you can then manually or programmatically retrieve them. (Hilary Cotter)

You could also set up a job to regularly poll the conflict table.

 


(SQL 2005) is there a way to set "not for replication" flag on an existing column which is defined as identity, to "Not For Replication"?

Have a look at the new procedure sp_identitycolumnforreplication

 


(SQL 2005) How to get round the (conflict) problems encountered when using GetDate() in filters (Nate Cook)?

Nate Cook found that he was getting bogus conflicts intermittently. The problem did not occur in Sql Server 2000 and was specific to using getdate() in the subset_filter for a table - especially if you have other child tables being filtered by join filters on the main table that has that subset_filter specified. He worked with Microsoft for a month sending them metadata log files, etc. and now there is an MSDN entry describing the workaround - http://msdn2.microsoft.com/en-us/library/ms365153.aspx.
The only thing not described in the above link is the fact that a potential symptom of using getdate() in filters is the existence of intermittent bogus conflicts: e.g. "The record was updated at the subscriber and at the publisher. Which version do you want to keep?" when in actuality the record was only updated at the subscriber and not at the publisher. Or it might say the record was deleted at the publisher when it wasn't at all. Please bear this in mind.

 


(SQL 2005) How do add a PK to merge replication?

sp_repladdcolumn @source_object = 'Table3'
, @column = 'xxx'
, @typetext = 'uniqueidentifier not null default(newid()) CONSTRAINT UPKCL_Table3 PRIMARY KEY CLUSTERED'
, @publication_to_add = 'northwindtable3'
, @force_invalidate_snapshot = 0
, @force_reinit_subscription = 0

If the table has data already, there are issues of uniqueness, hence I have used the default to avoid this problem. In this case I couldn't add an Integer PK. BTW this is all relatively straightforward in SQL Server 2005 with the nice new @replicate_ddl parameter.


(SQL 2005) How do I control the flow of data using merge replication?

There are 3 options:

(1) SQL Server Upload Only Conflict Resolver. BOL: "Changes uploaded to the Publisher are rejected; changes are downloaded to the Subscriber". (set at design time for the publication)

(2) the -EXCHANGETYPE parameter (can be set at run time for the subscription)

(3) @subscriber_upload_options (set at design time for an article of the publication)


new! How to....... combine filters and joins?

This could be made into an article, but put simply, if you have join filters, and a static table filter on each table in the join, the results are not filtered correctly, or at least not at all intuitively.

eg, consider I merge replicate the 2 tables: Customers and Orders from the Northwind database. These are joined by a PK - FK relationship - a customer can place several orders. If I create a join filter to link the tables, all 'ordering' Customers and their associated Orders are replicated.  I then add a filter clause on the Customers table (parent) to restrict the output to a particular customer: customerid = 'VINET'. The resulting (automatically created) merge view for Orders restricts the results to 5 orders - those belonging to customer 'VINET'. So, on initailization one customer and 5 associated orders are replicated. However, what if I also put a filter on the Orders table: customerid = 'ALFKI'. Logically this should further restrict the replicated Orders. However, on initialization 11 orders are now replicated. In this case the following view is created:

create view [NorthwindCustomersMerge_Orders_VIEW] 
as select alias_2C2031330F9D40AA96EB39B49AF00F41.* from [dbo].[Orders] alias_2C2031330F9D40AA96EB39B49AF00F41 
where rowguidcol in ( select [Orders].rowguidcol from [dbo].[Orders] [Orders] , [NorthwindCustomersMerge_Customers_VIEW] [Customers] 
where ( ( customers.customerid = orders.customerid) ) and ({ fn ISPALUSER('A23CFAD1-BDAC-4E0E-8447-BCD79E786943') } = 1) 
union select [dbo].[Orders].rowguidcol from [dbo].[Orders] where ( (customerid = 'ALFKI')
and ({ fn ISPALUSER('A23CFAD1-BDAC-4E0E-8447-BCD79E786943') } = 1) ) 
and ({ fn ISPALUSER('A23CFAD1-BDAC-4E0E-8447-BCD79E786943') } = 1) 

I've highlighted the crucial bits in red. The first part of the view refers to the join and the NorthwindCustomersMerge_Customers_VIEW view contains the customerid = 'VINET' clause. The second part refers to the order filter, but the 2 parts are UNIONED, rather than an AND clause being used. This means that rows arriving as part of the join, but which don't have a customerid = 'ALFKI' are additionally returned! I'll verify if this also occurs in SQL Server 2005.

 


How to....... dynamically change the filter clause?

The question was asked with reference to the following tables:

Files table: ID, Name, Type
Documents table: ID, FileID, Name, DocPath
Type lookup table: ID, Name

(so there are many documents in each file). Before the user goes offline, he asks to "download" several files he's been working on to his laptop along with the related documents. Note that the solution to replicate all files and documents wasn't acceptable.

Changing the initializing data retrospectively isn't possible directly unless you have a separate publication for each subscriber, change the filter clause and then reinitialize. However, using static filters, it is possible to reallocate records at the highest level, and the effect will propagate downwards by virtue of the join filters. This will allow you to simulate changing the filtering dynamically. Practically speaking, there would be have to be another table ("File_Subscriber") which relates files to subscriber, and table joins would then relate the other tables, while the static filter would apply to the "File_Subscriber" table only. Checking out another file by a subscriber would be an insert into the "File_Subscriber" table. Perhaps surprisingly, merge replication will, on synchronization, replicate not only this new record, but all related records by virtue of the join table filters, so in effect, we can reinitialize each time but dynamically. I'll create an article on this interesting merge be



How to....... Find a list of pending merge changes?

Have a look at this procedure. 

new! How to....... Manually start the merge agent?

C:\Program Files\Microsoft SQL Server\80\COM>replmerg -Publisher DH1791628
-PublisherDB xxxPublisher -Publication xxxPublishertClients -Subscriber
DH1791628 -SubscriberDB sub1 -Distributor DH1791628 -DistributorLogin sa
-DistributorPassword sa


How to....... Manually change the identity range on a subscriber?

Firstly, this shouldn't really be done! If you are using automatic range management this'll be taken care of when you synchronize (run the merge agent). However, if it is not possible for you to connect to the publisher, you could manually update MSrepl_identity_range on the subscriber. This table is used to check if the subscriber has used up its range or reached the threshold. The new range you set would be obtained from MSrepl_identity_range on the distributor, which is the master table and is used to generate new values. The values in this table (MSrepl_identity_range on the distributor) would need to be changed to avoid a future potential conflict. Finally, the check constraints on the subscriber would need updating accordingly.

 


How to.......  use dynamic filters and change the actual filter clause for each subscriber?

This can be achieved using a lookup table as an additional article.

To test this, I used 2 tables - Region and HostnameLookup - shown below. The HostnameLookup table defines the multiple values I'm interested in. I use dynamic filters to filter the HostnameLookup table using HOST_NAME() and a join filter to join to the region table. Editing the 2nd step on the merge agent's job to include: -Hostname PaulsComputer means that only 2 regions get replicated. I've listed the exact text below in case you want to recreate it to test.

Region
RegionID, RegionDescription, rowguid
1, Eastern, 9A6377F0-70DF-4A5C-962D-B41A41EFA82B
2, Western, C0CAEFAD-7B8C-43D6-87ED-920494A5C60C
3, Northern, 6CD9AA33-BE2D-4DCF-B447-745A3B86818E
4, Southern, B4826E41-96D6-457C-8645-DD4984AE3BF5

HostnameLookup
RegionDescription, Hostname, rowguid
Northern, PaulsComputer, 2367C78A-1001-417B-A3B1-1C74B23F8131
Southern, PaulsComputer, 4F563C4D-8479-4A7D-A938-490DD514F12A


Filter Clause for HostnameLookup:
SELECT <published_columns> FROM [dbo].[HostnameLookup]
WHERE HostnameLookup.Hostname = HOST_NAME()

Filter Clause for Region:
< All rows published >

Join Filter:
Filtered table is HostnameLookup
Table to Filter is Region

SELECT <published_columns> FROM [dbo].[HostnameLookup]
INNER JOIN [dbo].[Region] ON Hostnamelookup.regiondescription = region.regiondescription

Edit the 2nd step on the merge agent's job to include: -Hostname PaulsComputer

Run the snapshot then merge agents and only 2 regions should be replicated.


How to.......  troubleshoot inserts on the publisher being removed?

 

This is called the "compensate_for_errors" problem. If a change from publisher fails to get applied at the subscriber (for some reason, PK,FK,CHECK,etc constraints) it undoes the change at the publisher. So a insert from publisher when fails at the subscriber gets deleted at the publisher too. Similary a delete from publisher which fails at the subscriber, it gets re-inserted at the publisher. There is an associated KB article.

 


How to.......  troubleshoot network issues?

 

Run a ping -t for a day and then look at the statistics to see if a hicup occured.

You could run this keep alive script which will tell you exactly when you get a failure. Save this as c:\keepalive.sql


WHILE 1<>2
BEGIN
SELECT GETDATE()
WAITFOR DELAY '00:00:01'
END
GO

Here is the batch file that I use to run this script:
osql -S hilary2kp -E -i c:\keepalive.sql -n
date /t
time /t

(Hilary Cotter)

 


How to.......  upload new records then automatically have them removed?

 

This can be done by having a filter of 1=2 on the article (table). However, inserts made when the merge agent is synchronizing may not be removed.

 


  How to....... add a new article and have it appear?

  You can add the article using sp_addmergearticle. The subscribers will need to be SQL 2000. After you've added it, you run the snapshot agent. This will generate a complete snapshot but only the new article will be propagated by the merge agent. If your first initialization was a nosync one, then the new article will be added as a nosync one also ie the table must exist on the subscriber for this to work. If it was a sync one, then the table will be copied over as per normal.

 


How to....... exclude a column from replication but leave it on the publisher and subscriber?

  You could modify the update trigger as follows:

IF Not UPDATE(extra column name)
BEGIN
existing trigger code
END

The insert and delete triggers could be left as they are, as both should
propagate through the normal merge replication

 


How to....... report on the amount of updates, inserts and deletes done by publisher and subscriber over a period of time?

  select publisher_insertcount, publisher_updatecount, publisher_deletecount,
subscriber_insertcount, subscriber_updatecount, subscriber_deletecount from
dbo.MSmerge_history (Hilary Cotter)

 


How to....... add a lot of rows to one of my merged articles (a table), and not have the rest of the publication take ages to download?

  This is because you are using one agent and the changes are queued. In this situation, you can create a separate publication for each article, and have each one use its own agent. Modify the agent profiles to have a slow and fast profile (details to follow).

 


How to....... fix rows not being transferred on synchronisation?

  This can happen in 3 circumstances:

(1) Firstly when the filter was set to 1=2 and inserts were made while the merge agent was running

(2) If you bulk insert the rows and choose the defaults, then FIRE_TRIGGERS is false and consequently the rows are not added to MSmerge_contents. 

(3) If you do a fast-load using the Transform Data task in DTS:

In all cases case, you need to run sp_addtabletocontents to include the rows then resynchronise. Alternatively you can use sp_mergedummyupdate for a single row. For the fast load case, in future if you deselect the check box the triggers will fire.

 


How to....... use Dynamic Horizontal Filters and not have logins or computer names in each publication table?

  In Merge Replication, Dynamic Horizontal Filters can be used to partition data according to the subscriber. At first sight these don't seem too useful as they rely on the use of the SUSER_SNAME() and HOST_NAME() functions. Typical examples I've seen include a column in a replicated table which include logins or computernames, to which these filtering functions apply. This would seem to indicate that such columns need to be in each replicated table - not true! We can make them more useful in 2 different ways:

(a) in the case of HOST_NAME() there is a parameter for the replication merge agent - HOSTNAME - this can be set to be different from the computername, and so could be a business-related value. NB there is no corresponding SUSERSNAME parameter.

(b) We can also use a user defined function: eg MyUDF(SUSER_SNAME()). This function is coded to use a lookup table which map logins (or computernames) to a key column in the replicated table.

 


How to.......  configure one-way merge replication?

  Add -ExchangeType to the merge agent's job step parameters. The values are listed in BOL under the programming topic 'EXCHANGE_TYPE constant', but basically there are three options: 3=bidirectional, 2=Publishers->subscribers only and 1=Subscribers->Publishers only. Bidirectional is the default.
It might seem possible to create a new profile and add the new parameter (-ExchangeType in this case) to MSagent_parameters for the relevant profile_id (MSagent_profiles). Unfortunately, the parameters picked up from the profile are hardcoded in sp_MSvalidate_agent_parameter so not all the ones listed on the MS site are acceptable. To try to add a particular parameter, use sp_add_agent_parameter - it'll return an error if it is not acceptable, in which case you must resort to the command-line arguments..

 


How to....... avoid subscriber deletes? - when I use filtered articles and add a record on a subscriber, it is later deleted?

  Filtering works by creating a view on the publisher. Initialisation doesn't send this view to the subscriber, and it is only checked on the publisher. So, you can add a record on the subscriber and on synchronisation this record will be sent as an insert to the publisher. here, the filter is checked, and a delete is downloaded to the subscriber. If this is not the way you want it to work you have 2 choices:

(a) modify the insert trigger on the subscriber to ensure it doesn't write the changed record to MSmerge_contents.

(b) use partitioned views to partition your data based on the original merge replication filter and only replicate one table.

 


How to....... get the replicated row count, table, and date/time that the changes occurred for Merge replication.

  Select m.name,Count(m.name) as Total, CONVERT(varchar(25),mg.coldate,100) as [Date] FROM MSmerge_contents mc INNER JOIN sysmergearticles m ON mc.tablenick = m.nickname INNER JOIN msmerge_genhistory mg ON mc.generation = mg.generation GROUP BY mg.coldate, m.name ORDER BY mg.coldate desc (Jim Johnston)
   
  Error Messages.......

Error Messages.......When the merge agent runs I notice there are blocking issues then it experiences a timeout.

  To find out more information about the cause of your blocking issues you might like to use the MS scripts. If it is simply a matter of having a lot of data modifications being synchronized then you need to optimize the merge agent. You could:

increase -DownloadGenerationsPerBatch
make sure -MetadataRetentionCleanup is 1 and even run
sp_mergemetadataretentioncleanup manually
run the merge agent more frequently, so as to not accumulate changes
decrease the -PollingInterval if you are running continuously
increase -QueryTimeOut

Alternatively, if you accept a high latency, you might run the merge agent out of hours.

 


Error Messages.......On creating the snapshot I receive the following error: CREATE UNIQUE INDEX terminated because a duplicate key was found for index ID 5. Most significant primary key is 'type 24, len 16'. (Source: MY_SQL_SERVER (Data source); Error number 1505).

  If you are using merge replication can you check for duplicates in the rowguid column - another poster had this issue when he copied a row back into the same table. If there are any duplicates, then they'll need to be removed - either you can delete the row or drop then readd the rowguid column.

 


Error Messages....... I have a problem when trying to publish articles for merge replication. During execution of the snapshot agent I receive the following error "The process could not bulk copy out of table '[dbo].[table_name]'.

  Basically it means the snapshot agent locked up, timed out, was blocked, or somehow deadlocked. What you do is stop and restart the snapshot agent. If you are dealing with a large table, you may need to manually transfer it to the subscriber. There are cases where the size of the table becomes nearly impossible to get a snapshot to complete.

 


Error Messages......."The process could not enumerate changes at the 'Subscriber'."

  This is a generic , high-level error message simply indicating that the merge agent ran into a problem moving changes from the subscriber to the publisher. It can be caused by several different problems, and is not necessarily a bug. To get more info, you could enable logging on the merge agent (-output c:\somefile.log -outputverboselevel 3). Alternatively, most of these merge errors are solved by simply restarting the merge agent.

 


Error Messages.......Failed to enumerate changes in the filtered articles - what does it mean?

  There is a KB article and a related hotfix for this issue: http://support.microsoft.com/default.aspx?scid=kb;en-us;814916

 


new! Error Messages.......when I insert a row on site1(Publisher) the row gets inserted to msmerge_contents at Site2 (Site2 acts as a Subscriber for Site1 and also acts as publisher). However it doesn't get replicated to Site3 (Site3 acts as a subscriber for Site2.

Check to see if you are using local subscriptions. All subscriptions need to be global for this to work.

 


General......What is a conflict?

 

This is not so obvious as it first seems! Firstly, when you configure merge replication, you choose global subscriptions (priority numbers) or local subscriptions (first subscriber gains priority of Publisher). There are 3 combinations:

(a)     Just global subscriptions. Highest value wins and publisher always wins.

(b)     Just local subscriptions. First subscriber wins and publisher always wins

(c)     Both local and global subscriptions. If local merge agent synchronises first, he wins. If global synchronises first, he beats any locals and then competes as usual with any other globals.

 

So if we have the following topology: Subscriber1--------Publisher---------Subscriber2, it breaks down as follows:

(a)     Just local. Change the same row at each subscriber. Synchronize Subscriber1 and then Subscriber2. The second synchronization will register a conflict and explain that Subscriber1's value wins.

(b)     Global. Consider that subscriber1 has a priority of 75 and subscriber2 has a priority of 50. They both change the same record. If Subscriber1 synchronizes then Subscriber2, there is a resolved conflict. However, if Subscriber2 synchronises first then Subscriber1, the value is overwritten and no conflict registered. It is only when Subscriber2 resynchronises that a conflict is registered. So, the rule is that a conflict occurs only when a lower valued (priority) subscriber tries to overwrite a higher valued one.

   

Oct 2004