| |
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. |
| |
|