Benutzer mit den meisten Antworten
Konflikt bei merge replication

Frage
-
hi zusammen,
wir haben eine zentrale db und unsere aussen clients, die eine CE db besitzen. nun haben wir den fall getestet, dass 2 CE datenbanken, bei einer tabelle jeweils einen neuen eintrag hinzufügen. wir haben dafür gesorgt dass beide einträge die selben IDs bekommen und dann versucht diese nach einander mit der zentral-db zu mergen. natürlich haben sowohl die tabelle in der zentral db als auch die CE-Tabellen rowguid-felder.
wer zuerst synchronisiert, kriegt seinen eintrag in die zentral db reingeschoben. der zweite mit der selben id (es handelt sich um eine integer-id die als primary key der tabelle benutzt wird) bekommt eine fehlermeldung dass es einen konflikt gegeben hat.
das macht irgendwie keinen sinn... wozu hat man dann die global eindeutigen RowGUIDs? warum kann der merge-replicator nicht bei gleich vergebenen primary keys diesen konflikt umgehen? wenn das nicht möglich ist, dann verstehen wir den sinn von merge-replication gar nicht mehr.
bitte um hilfe und hinweise.
besten dank im voraus,
A.V.
Antworten
-
Hallo AV,
Du hast selbstverständlich Recht, dass die ID (sofern es IDENTITY sind) von der Publikation selbst verwaltet werden. Das setzt aber voraus, dass die Abonnenten nach der Erstellung der Publikation einen entsprechenden Snapshot erhalten. Dann werden die (wie in Deinem obigen Codebeispiel aufgeführten) Id ranges erstellt / verwaltet.
Ich würde vorschlagen, wie folgt vorzugehen:
1. Publikation ist erstellt
2. Snapshot erstellen
3. Abonnenten neu initialisieren (mit Angabe, dass neuer Snapshot verwendet wird!)Wir haben solche Szenarien, wie von Dir beschrieben, in mehreren Standorten laufen und noch keine Probleme mit den ID gehabt!
PS: Du hast die Tabelle jetzt aber aus der bestehenden Replikation gescripted, gell? :-)
Uwe Ricken
Microsoft Certified Database Administrator SQL Server 2005
db Berater GmbH
http://www-db-berater.de- Als Antwort markiert Deeeeeeeeeeee Dienstag, 26. Oktober 2010 09:09
-
habs jetzt mittlerweile gelöst...
die publisher-datenbank ist NICHT in der lage aufgrund der IDENTITY-Eigenschaft die zu synchronisiernden IDs zu ignorieren und ihre eigenen IDs einzutragen, ABER dafür gibt es die ID-Ranges wie der Uwe schon oben geschrieben hat.
http://technet.microsoft.com/en-us/library/ms152543.aspx
also zuerst die publication anlegen, dann die jeweiligen subscriptions. subscriptions erhalten nach dem ersten sync unterschiedliche ID-Ranges (subs a : 2001, subs b : 3001). dies kann man mithilfe von sql server management studio prüfen (mit der CE-DB verbinden, dann rechtsklick auf der DB -> edit table. -> Identity Seed).
ob dies eine kluge lösung von microsoft wäre, ist eine andere frage. ich weiss nicht warum man sich für diese lösung entschieden hat. die klügere wäre, dass die publisher-datenbank, wenn sie identity felder als primary key verwendet, auch beim mergen der daten (empfangen von neuen daten von subscribern), wenn es sich um inserts handelt und nicht updates, ihre eigenen neuen IDs einträgt und nicht die von den subscribern. so würde man auch keine ID-Ranges brauchen...
- Als Antwort markiert Deeeeeeeeeeee Dienstag, 26. Oktober 2010 09:16
Alle Antworten
-
Hallo AV,
dann scheinst Du das Konzept der Replikation nicht so richtig verstanden zu haben. Zunächst einmal ist die Rowguid entscheidend, da sie tatsächlich unique ist. Das ist z. B. ein Integer (wie in Deinem Beispiel) nicht.
Da das Integer-Attribut bei Dir aber der PK ist, läuft zwangsläufig Deine Replikation gegen die Wand. Wenn Du tatsächlich über solche Id die Eindeutigkeit Deiner Daten sichern möchtest, dann solltest Du mit IDENTITY-Spalten arbeiten. Dabei ist aber darauf zu achten, dass der Datenrange durch die Replikation verwaltet wird.
Eine typische Tabelle (bei Berücksichtigung als Replikat) sähe dann wie folgt aus:
Wenn Du dann das Abonement erzeugst wird danach ein Snapshot erstellt. Dieser Snapshot wird dann auf die Abonnenten verteilt und gut ist ;-)CREATE TABLE dbo.Replikat ( id INT NOT NULL IDENTITY (1, 1) NOT FOR REPLICATION, .... rowguid uniqueidentifier NOT NULL DEFAULT (newid()), CONSTRAINT pk_Replikat PRIMARY KEY NONCLUSTERED (Id) ) GO -- Bei Triggern auch darauf achten, dass sie bei Replikaten nicht gefeuert werden, wenn es ein Einfügemechanismus des Replikats ist!!! CREATE TRIGGER dbo.trg_Replikat_Insert ON dbo.Replikat FOR INSERT NOT FOR REPLICATION AS ... GO
Uwe Ricken
Microsoft Certified Database Administrator SQL Server 2005
db Berater GmbH
http://www-db-berater.de -
Hallo und danke für die antwort.
mein beispiel ist aber nicht viel anders wie das von dir vorgeschlagene beispiel.
CREATE TABLE [dbo].[I_INSTRS_DEF]( [INSTRUMENT_DEF_ID] [int] IDENTITY (1,1) NOT FOR REPLICATION NOT NULL , [THE_DATE] [datetime] NULL CONSTRAINT [DF__I_INSTRS___THE_D__403A8C7D] DEFAULT (getdate ()), [THE_OPERATOR] [nvarchar](50) NULL CONSTRAINT [DF__I_INSTRS___THE_O__412EB0B6] DEFAULT (user_name ()), [INSTRUMENT_NAME] [nvarchar](50) NOT NULL , [INSTRUMENT_DESC] [nvarchar](128) NULL , [TECHNICAN_ID] [numeric](11, 0) NULL CONSTRAINT [DF__I_INSTRS___TECHN__4222D4EF] DEFAULT ((0)), [COMMENT_R] [nvarchar](255) NULL , [LOCKED] [numeric](1, 0) NULL CONSTRAINT [DF__I_INSTRS___LOCKE__4316F928] DEFAULT ((0)), [ROWGUID] [uniqueidentifier] ROWGUIDCOL NOT NULL CONSTRAINT [DF__I_INSTRS___ROWID__440B1D61] DEFAULT (newsequentialid()), CONSTRAINT [SYS_C003566] PRIMARY KEY CLUSTERED ( [INSTRUMENT_DEF_ID] ASC )WITH (PAD_INDEX = OFF , STATISTICS_NORECOMPUTE = OFF , IGNORE_DUP_KEY = OFF , ALLOW_ROW_LOCKS = ON , ALLOW_PAGE_LOCKS = ON ) ON [PRIMARY] ) ON [PRIMARY] GO ALTER TABLE [dbo].[I_INSTRS_DEF] WITH NOCHECK ADD CONSTRAINT [repl_identity_range_62929DB8_1756_4C7B_A59A_DB06E6F7DE37] CHECK NOT FOR REPLICATION (([INSTRUMENT_DEF_ID]>(118) AND [INSTRUMENT_DEF_ID]<=(1118) OR [INSTRUMENT_DEF_ID]>(1118) AND [INSTRUMENT_DEF_ID]<=(2118))) GO ALTER TABLE [dbo].[I_INSTRS_DEF] CHECK CONSTRAINT [repl_identity_range_62929DB8_1756_4C7B_A59A_DB06E6F7DE37]
da unsere tabellen mit den jeweiligen int-feldern als PKs bereits existierten und wir erst im nachhinein merge-publication darauf angelegt haben, ist es ja nicht seltsam dass unsere PKs Integerwerte haben. Durch das anlegen einer publication werden ja ROWGUID-felder in den jeweiligen tabellen mit der rowguidcol-eigenschaft angelegt. in diesem moment sollte doch für das system klar sein, dass die rowguids als unique ids für die replikationen benutzt werden sollen.
was die trigger angeht, wir haben momentan, ausser den vom system angelegten merge-triggern keine weiteren drin.
unsere Integer-Felder die auch die primary keys sind, sind bereits IDENTITY felder. sie werden automatisch von der db gesetzt und inkrementiert. das problem bei der sache ist, wenn 2 clients jeweils einen neuen eintrag erfassen und diese dann synchronisieren wollen, das system auf der zentralen seite bereits kennt dass es um 2 INSERTS geht und keine UPDATES. bei updates würde es ja die werte einfach überschreiben, aber bei inserts meldet er einen konflikt, da er keine doppelten werte für PK felder eintragen kann. das heisst, es müsste eigentlich beim 2. eintrag, die ID automatisch geändert werden (z.b. die nächst frei id wählen). aber was mich am meisten wundert ist : die integer-id-felder sind doch IDENTITY-Felder. warum schluckt die zentral-db bei einer replikation die IDs von den Clients? sollte sie nicht diese IDs ignorieren (falls es sich dabei um inserts handelt) und ihre eigenen werte eintragen? lediglich bei updates sollte die zentral-db die IDs berücksichtigen und die jeweiligen werte überschreiben....
besten dank im voraus...
-
Hallo AV,
Du hast selbstverständlich Recht, dass die ID (sofern es IDENTITY sind) von der Publikation selbst verwaltet werden. Das setzt aber voraus, dass die Abonnenten nach der Erstellung der Publikation einen entsprechenden Snapshot erhalten. Dann werden die (wie in Deinem obigen Codebeispiel aufgeführten) Id ranges erstellt / verwaltet.
Ich würde vorschlagen, wie folgt vorzugehen:
1. Publikation ist erstellt
2. Snapshot erstellen
3. Abonnenten neu initialisieren (mit Angabe, dass neuer Snapshot verwendet wird!)Wir haben solche Szenarien, wie von Dir beschrieben, in mehreren Standorten laufen und noch keine Probleme mit den ID gehabt!
PS: Du hast die Tabelle jetzt aber aus der bestehenden Replikation gescripted, gell? :-)
Uwe Ricken
Microsoft Certified Database Administrator SQL Server 2005
db Berater GmbH
http://www-db-berater.de- Als Antwort markiert Deeeeeeeeeeee Dienstag, 26. Oktober 2010 09:09
-
also hab einen neuen snapshot erstellt (rechtsklick auf publikation > reinitialize all subscriptions > use a new snapshot > generate the new snapshot now > Mark for reinitialization)
zur sicherheit hab ich vorher den snapshot ordner manuell entfernt. der snapshot wurde angelegt und die subs reinitialisiert. hab einen neuen eintrag auf der CE db erfassst mit einer krummen ID. diese dann synchronisiert und die zentral DB hat die neue ID (die neue von der CE-DB) schon wieder geschluckt. warum? sollte die CE-ID nicht ignoriert und durch eine von der IDENTITY-Eigenschaft generierten ID der zentral-db ersetzt werden?
-
Hallo AV,
lösche doch bitte mal einen Abonennten und setze ihn komplett neu als Abonnent auf. Ev. hat der noch seinen eigenen festgelegten ID-Bereich hinterlegt.
Nachdem der Abonnent gelöscht ist, einfach noch einmal neu anlegen.
Uwe Ricken
Microsoft Certified Database Administrator SQL Server 2005
db Berater GmbH
http://www-db-berater.de -
- hab bei der CE-DB eine subscription gelöscht
- bei der publication : (rechtsklick auf publikation > reinitialize all subscriptions > use a new snapshot > generate the new snapshot now > Mark for reinitialization)
- bei der CE-DB eine neue Subscription angelegt
- diese dann synchronisiert
- einen neuen eintrag auf der CE-Seite erfasst
- die ce-db nochmal synchronisiert
=> die id wurde wieder geschluckt.
ich dreh hier langsam durch... ich kann dir auch alles mit screenshots schicken damit du siehst dass ich das alles auch wirklich so gemacht hab.
-
gibt es keine lösungsvorschläge?
hier eine kurze zusammenfassung des problems :
die publisher-datenbanktabellen haben jeweils ein integer-feld als primary key welches ein identity-feld ist. diese übernehmen aber beim mergen die IDs aus den subscriber-datenbanken. dies führt dazu dass es zu konflikten kommt, wenn 2 subscriber zufällig die selben IDs zu inserten versuchen. dieses problem wäre gelöst, wenn die publisher-db diese IDs aufgrund seiner identity-eigenschaft ignorieren, und ihre eigenen IDs eintragen würde...
Bitte um hilfe!
-
habs jetzt mittlerweile gelöst...
die publisher-datenbank ist NICHT in der lage aufgrund der IDENTITY-Eigenschaft die zu synchronisiernden IDs zu ignorieren und ihre eigenen IDs einzutragen, ABER dafür gibt es die ID-Ranges wie der Uwe schon oben geschrieben hat.
http://technet.microsoft.com/en-us/library/ms152543.aspx
also zuerst die publication anlegen, dann die jeweiligen subscriptions. subscriptions erhalten nach dem ersten sync unterschiedliche ID-Ranges (subs a : 2001, subs b : 3001). dies kann man mithilfe von sql server management studio prüfen (mit der CE-DB verbinden, dann rechtsklick auf der DB -> edit table. -> Identity Seed).
ob dies eine kluge lösung von microsoft wäre, ist eine andere frage. ich weiss nicht warum man sich für diese lösung entschieden hat. die klügere wäre, dass die publisher-datenbank, wenn sie identity felder als primary key verwendet, auch beim mergen der daten (empfangen von neuen daten von subscribern), wenn es sich um inserts handelt und nicht updates, ihre eigenen neuen IDs einträgt und nicht die von den subscribern. so würde man auch keine ID-Ranges brauchen...
- Als Antwort markiert Deeeeeeeeeeee Dienstag, 26. Oktober 2010 09:16