Home  |  Articles  |  Scripts  |  Consultancy  |  FAQs  |  Links  |  SSIS

 

Merge Changes in SQL Server 2005: (2) - Dynamic Filters and Unidirectional Merge

Introduction

This article begins to take a look at some of the new functionality in merge replication, using the SQL Server 2005 Beta CTP of April 2005. Specifically, I was interested in how to implement two different techniques: dynamic filters and unidirectional merge replication. Why these in particular? Well, because I had always though that the SQL 2000 implementation was rather awkward :) It involved manually editing the text in job steps, which is very much the exception in replication administration. This makes maintenance more difficult, and I had previously made a feature request that these features be added to the merge profile parameters which would avoid having to make such low-level editing. So, I was interested to see if this functionality had been changed to make the configuration more sophisticated and our lives easier.

Background

In case the reader is not entirely familiar with these concepts, here's an (extremely selective) potted intro.

(a) Dynamic Filters

Filters may be static or dynamic. When static, each subscriber gets the same data. An example static filter is Country = 'UK'. In this case the table data is filtered on synchronization to ensure that each subscriber gets only UK data. Dynamic filters ensure that each subscriber gets (potentially) a different horizontal partition of data. The subscriber is identified in the filter clause via a dynamic function. An example dynamic filter is Country = HOST_NAME() where the function HOST_NAME() resolves to the NETBIOS name of the (pull) subscriber's computer. In order to avoid having to rename each subscriber's computer to have NETBIOS country names and so make all this work, a common solution is to use the -HOSTNAME parameter in the merge agent's job which overrides the value returned from the dynamic function eg -HOSTNAME Wales. Another, less-frequently used solution, is to implement UDFs but let's forget this for now. So, to summarize, the -HOSTNAME  parameter doesn't exist in the subscription setup or the profile, and in most cases DBAs have resorted to editing the merge agent's job to get it working.

(b) Unidirectional Merge

The value of -EXCHANGETYPE determines the direction of merge replication changes. Once again this is implemented by manually editing the merge agent's job step, placing -EXCHANGETYPE 1|2|3 as text. The values 1|2|3 (| means 'or') are explained below:

UPLOAD

1

Only merge Subscriber changes with the Publisher.

DOWNLOAD

2

Only merge Publisher changes with the Subscriber.

BIDIRECTIONAL

3

Merge all changes between the Publisher and Subscriber (default).

By default, changes flow in either direction (-EXCHANGETYPE = 3). Entering a value of 2 means that changes to a replicated article at the subscriber are not prohibited, are recorded in the merge metadata tables via merge triggers, and are subsequently filtered out when the merge agent synchronizes. This means there may be a huge amount of metadata unnecessarily recorded, slowing down data changes and synchronization.

So, if we combined together dynamic filters and unidirectional changes, a merge agent's job step to have downloads only of Wales data would look like this:

How have things changed in SQL Server 2005?

(a) Dynamic Filters

When defining the subscriber, you are faced with a form allowing you to define (hardcode) a value for the HOST_NAME() function, which overrides the NETBIOS name.

Scriptwise this corresponds to

sp_addmergesubscription @hostname = 'hostname'

and is referred to as the "partition definition". So, we no longer have to edit job steps.

As in SQL Server 2000, this value overrides the value returned by the HOST_NAME() function. The HOSTNAME parameter input taken from UI is used to set the properties in the MSsubscription_properties table so that the merge agent can read the property from this table for subsequent syncs.  This is true for pull subscriptions.  However in case of push subscriptions there isn't a table that maintains such properties on the publisher hence the "-HOSTNAME host_name" string is put in the job command line at the distributor.  So, if you forget to assign a value when creating the subscription, it is still possible in push subscriptions to revert to SQL Server 2000 methodology, and manually place the "-HOSTNAME host_name" string in the merge job step. The command line -HOSTNAME parameter, if specified, (either by the DBA or by the UI), it is always used and always overrides everything else. For example, the HOSTNAME property in MSsubscription_properties table can be overridden by specifying a –HOSTNAME value in the command-line.   

(b) Unidirectional Merge

When adding an article, there is an option to define the "subscriber_upload_options":

sp_addmergearticle @subscriber_upload_options= subscriber_upload_options

This defines restrictions on updates made at a Subscriber (with a client subscription). The parameter "subscriber_upload_options" is a tinyint, and can have one of the following values.

0 No restrictions. Changes made at the Subscriber are uploaded to the Publisher.
1 Changes are allowed at the Subscriber, but they are not uploaded to the Publisher.
2 Changes are not allowed at the Subscriber.

So, how is this actually implemented?

Option 0 is defined as "no restrictions" and is the bidirectional default. This is much like using "-EXCHANGETYPE = 3" in SQL Server 2000. There are the usual 3 triggers on the subscriber to log all data changes to the merge metadata tables: MSMerge_ins_...MSMerge_upd_...MSMerge_del_...
Option 1 is defined as "download only, but allow subscriber changes". This is equivalent to "-EXCHANGETYPE = 2" but in this case there are no triggers at all on the subscriber. So, although these 2 methods are logically equivalent, the implementation has become much more sophisticated in SQL Server 2005 :). There is no firing of triggers to unnecessarily log metadata at the subscriber, which makes both subscriber data changes and the subsequent synchronization significantly faster.
Option 2 disallows all subscriber changes. In this case there is a special trigger - MSmerge_downloadonly_.... - which will rollback any attempt to change subscriber data. This option is new to SQL Server 2005 and has no equivalent in SQL Server 2000. If a user attempts to perform an update, they'll be faced with this message:

Msg 20063, Level 16, State 1, Line 1
Table '(null)' into which you are trying to insert, update, or delete data has been marked as read-only. Only the merge process can perform these operations.

The "-EXCHANGETYPE [1|2|3]" parameter to the merge agent's job is still available, even though it seems to have been largely superseded by the new functionality. This parameter still works with bidirectional (@subscriber_upload_options=2) but on efficiency grounds I wouldn't recommend using -EXCHANGETYPE as an alternative to the corresponding @subscriber_upload_options option in general. Perhaps an exception could be made in the case of -EXCHANGETYPE = 1 as there is no corresponding value for @subscriber_upload_options.

NB:  The EXCHANGETYPE specification skips the upload phase or the download phase of the merge agent and affects all articles in the publication whereas the @subscriber_upload_options in sql2005 is specified at article level.  So you can now have a subset of articles in the publication as download only.  This is a typical customer scenario where there are some tables that are lookup only (such as product price catalog) but there are other articles that are order entry which need to upload as well. 

One final point - to take advantage of this property (@subscriber_upload_options) the subscription must be marked as a 'Client' subscription and not the default of 'Server' subscription (see below). If you leave the default 'Server' option, the subscriber will always be created as bidirectional.

Conclusions

We've looked at the SQL Server 2005 replacements for the -EXCHANGETYPE and -HOSTNAME parameters in merge replication. The new functionality is a big step forward as both are now explicitly set in the publication and subscription properties. This is not implemented as additional merge profile parameter changes as I had expected (and requested) but it achieves the same end - no more hacking of replication jobs to get things working. In the case of the -EXCHANGETYPE replacement (@subscriber_upload_options) we see a significant improvement in performance and additionally the granularity to control matters at an article level rather than applying to the complete subscription.