<html>
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=windows-1252">
</head>
<body>
<p>Hallo Frank,<br>
</p>
<p>Ich weiß nicht, ob es was zur Lösung der doppelten Objekte
beitragen kann aber ich wollte hier mal kurz das Konzept
darstellen, wie wir beim Einlesen von neuen Objektversionen
vorgehen.</p>
<p>Bei uns gibt es die Variante "kill" nicht, es wird also alles
historisch gesetzt. Aber unabhängig davon, ob man nun löscht oder
historisch setzt, hat man ja bei beiden Varianten das schon
angesprochene Problem, dass es während eines Einlesevorgangs Fälle
gibt, bei denen zuerst das Replace kommt und erst danach das
Insert. Die Reihenfolge ist also vertauscht.</p>
<p>Ein Trigger, der beim Einlesen des Replace-Objekts durch einen
Eintrag in die delete-Tabelle ausgelöst wird, kann aber noch gar
nichts machen, da eben durch das fehlende Insert die
Vorgängerobjektversion noch nicht da ist. Deswegen sind wir dazu
übergegangen, das Beenden der historisch gewordenen
Objektversionen erst ganz am Ende des Einlesevorgangs zu machen.
Denn dann wurden auch alle Inserts eingelesen.</p>
<p>Das Beenden der historisch gewordenen Objektversionen erfolgt bei
uns durch den Aufruf der Funktion "execute_hist_operations()", zu
finden hier: [1]<br>
</p>
<p>Diese Funktion verwendet die Informationen aus der Tabelle
"delete", um die Objekte zu beenden. Voraussetzung dafür ist
natürlich, dass dort auch die richtigen Informationen drin stehen.
Leider schreibt ogr2ogr nicht in allen Fällen die notwendigen
Infos dort rein. Deswegen hängt an der Tabelle "delete" ein
"BEFORE INSERT"-Trigger mit der Trigger-Funktion
"log_hist_operations()" [2], die dafür sorgt, dass die benötigten
Infos dort korrekt eingetragen werden.</p>
<p>Wir verwenden dieses Konzept der Fortführung in mehreren
Landkreisen nun schon ein paar Jahre und es läuft mittlerweile
sehr stabil und fehlerfrei.</p>
[1]
<a class="moz-txt-link-freetext" href="https://github.com/srahn/kvwmap/blob/kvwmap/plugins/alkis/db/postgresql/schema/2018-08-13_15-12-00_ignore_dublicates_trigger.sql">https://github.com/srahn/kvwmap/blob/kvwmap/plugins/alkis/db/postgresql/schema/2018-08-13_15-12-00_ignore_dublicates_trigger.sql</a>
<p>[2]
<a class="moz-txt-link-freetext" href="https://github.com/srahn/kvwmap/blob/kvwmap/plugins/alkis/db/postgresql/schema/2017-12-20_14-36-50_log_hist_operations.sql">https://github.com/srahn/kvwmap/blob/kvwmap/plugins/alkis/db/postgresql/schema/2017-12-20_14-36-50_log_hist_operations.sql</a></p>
<p>Viele Grüße,</p>
<p>Stefan Rahn</p>
<pre class="moz-signature" cols="72">--
GDI-Service
Friedrichstraße 16
18057 Rostock
Tel: 0381 40344445
E-Mail: <a class="moz-txt-link-abbreviated" href="mailto:stefan.rahn@gdi-service.de">stefan.rahn@gdi-service.de</a>
gdi-service.de</pre>
<div class="moz-cite-prefix">Am 30.04.2020 um 14:13 schrieb Jäger,
Frank (KRZ):<br>
</div>
<blockquote type="cite"
cite="mid:F2176AE4E9FFAF45BEA8D84DD6F4AF1A530C8B19@skrzmxmbx01">
<pre class="moz-quote-pre" wrap="">Moin!
ich bin einem Fehler auf der Spur, der nur unter bestimmten Bedingungen auftritt.
Der Fehler führt zu inkonsistenten Daten aber nicht zu Meldungen beim Konvertieren, er bleibt daher zunächst unentdeckt.
Die Wirkung: Die Datenbank enthält doppelte Objekte. Alte Versionen bei einem "Replace" werden nicht gelöscht.
Bedingungen:
Ab der Version 3.0-22 des ALKIS-Importers hat man beim Anlegen einer neuen Datenbank die Option "Historie führen".
Auswahl "ja" ist nicht betroffen, Bei Auswahl "nein" kann der Fehler auftreten.
Somit sind nur Sekundärbestände betroffen, die in den letzten Monaten neu angelegt wurden. Davor wurde als Standard "mit Historie" verwendet.
Der Import einer Erstabgabe ist noch korrekt, weil dabei nur "Insert" vorkommen.
Bei einer Aktualisierung kommen auch "Replace" vor, das kann dann zum Fehler führen.
Daten aus dem abgebenden ALKIS der Firma "ibR" sind nicht betroffen.
Der Fehler tritt nach meinen Beobachtungen nur auf, wenn Daten aus Software der Firma AED importiert wird. Zu Versionen kann ich nichts sagen.
Wenn die gennannten Bedingungen erfüllt sind, kann man z.B. mit folgendem SQL suchen:
SELECT gml_id, count(anlass) AS anzahl FROM ax_flurstueck
WHERE endet IS NULL
GROUP BY gml_id HAVING count(anlass) > 1;
Wenn diese Abfrage Zeilen liefert, dann habt ihr ein Problem. Wenn nichts zurück kommt, gibt es keine mehrfach vorkommenden Flurstücke. Der Fehler tritt aber auch in anderen Tabellen auf.
Lösung: Jürgen hat bereits einen Vorschlag zur Korrektur. Ich muss das aber noch umfangreich testen mit verschiedenen Daten.
Es wird aber wohl notwendig werden, die kaputten Datenbanken neu zu konvertieren.
Theoretisch denkbar ist auch in allen Tabellen nach doppelten Kennzeichen zu suchen und die jeweils ältere Version zu löschen.
Analyse der Fehlerursache:
Jetzt wird's kompliziert!
Das Einfügen von neuen Datensätzen in die Datenbank führt das Programm ogr2ogr direkt durch. Das Beseitigen der Vorgänger wird erledigt durch eine Trigger-Function in der PostgreSQL-Datenbank.
Die Funktion wird "getriggert" durch das Einfügen eines Satzes in die Tabelle "delete".
Es gibt zwei Typen von Functions. Beide sind in der Datenbank definiert, aber nur eine ist - entsprechend der Option - mit dem Trigger verbunden.
Die eine Version setzt dem Vorgänger ein Datum in seine Spalte "endet", das Objekt wird damit "historisch", verbleibt aber in der Datenbank. Die Anwendungen müssen darauf achten, solche Objekte nicht zu verwenden, wenn eine aktuelle Auswertung benötigt wird.
Eine andere Version des Triggers (Kill-Trigger) löscht das alte Objekt sofort aus der Datenbank statt es nur historisch zu machen.
Seit dem letzten Jahr gibt es nun im abgebenden ALKIS der Firma ibR eine neue Option "NBA Modellschwäche ausgleichen". Dazu sage ich hier nichts um mich nicht zu verzetteln. Damit werden dann aber massenhaft Objekte geliefert, die schon in genau gleicher Aktualität im Sekundärbestand vorhanden sind. Der Insert von ogr2ogr scheitert am eindeutigen Index.
Wenn dann der Kill-Trigger mit Replace ausgelöst wird, dann darf der nichts löschen, weil es keine alte Version dazu gibt. Erkannt wird das durch Vergleich des Zeitstempels alt/neu. Ist der gleich, dann wird nichts gelöscht, und das ist auch gut so.
Nun gibt es eine "Besonderheit" in den NAS-Replace-Daten aus AED-ALKIS. Ich denke, das ist ein Fehler, aber das mögen andere beurteilen.
In einem Replace-Block sieht das (stark vereinfacht) bei ibR so aus:
<wfsext:Replace vendorId="AdV" safeToIgnore="false">
<AX_Flurstueck gml:id="DE[*NEUE ZEIT*]">
<lebenszeitintervall>
<AA_Lebenszeitintervall>
<beginnt>[*NEUE ZEIT*]</beginnt>
</AA_Lebenszeitintervall>
</lebenszeitintervall>
....
<ogc:Filter>
<ogc:FeatureId fid="DE[*ALTE ZEIT*]" />
</ogc:Filter>
</wfsext:Replace>
Merke: Vorne neue Zeit, hinten alte Zeit.
Bei AED steht aber auch vorne in "<AX_Flurstueck gml:id="" die ALTE Zeit!?
Dies schlägt durch auf den Trigger. Der erkennt fälschlicherweise neu=alt, also Fall "Systemschwäche", also nichts löschen.
In diesem Fall ist das aber nicht richtig, weil in der Datenbank zu dem Zeitpunkt zwei Versionen stehen und die ältere müsste bei "Replace" ersetzt, d.h. gelöscht werden.
PS
Es hat eine Weile gebraucht, um das heraus zu finden.
Es grüßt aus dem Home-Office
Frank Jäger
Kommunales Rechenzentrum
Minden-Ravensberg/Lippe
Tel.: 05261 / 252 - 185
<a class="moz-txt-link-freetext" href="mailto:f.jaeger@krz.de">mailto:f.jaeger@krz.de</a>
<a class="moz-txt-link-freetext" href="http://www.krz.de/">http://www.krz.de/</a>
</pre>
<br>
<fieldset class="mimeAttachmentHeader"></fieldset>
<pre class="moz-quote-pre" wrap="">_______________________________________________
NAS mailing list
<a class="moz-txt-link-abbreviated" href="mailto:NAS@lists.osgeo.org">NAS@lists.osgeo.org</a>
<a class="moz-txt-link-freetext" href="https://lists.osgeo.org/mailman/listinfo/nas">https://lists.osgeo.org/mailman/listinfo/nas</a></pre>
</blockquote>
<pre class="moz-signature" cols="72">
</pre>
</body>
</html>