[Allegro] Mysteriöse Variable
Thomas Berger
ThB at Gymel.com
Mi Mai 2 17:01:24 CEST 2012
Lieber Herr Eversberg, lieber Herr Fischer,
> Es ist ganz einfach so: Das Programm weiß nicht und kann nicht irgendwie
> erschließen, was nach dem "find" geschehen wird. Z.B. kann es sein, daß
> mit einem "insert ..." etwas eingefügt und dann sofort der Satz mit
> "put" wieder gespeichert wird. Neuerdings muß man nicht mehr, und das
> ist den Notwendigkeiten und dem Trickreichtum des Locking zu verdanken,
> erst nach dem find noch "set lock" sagen, wodurch u.a. das
> Berechnen der Schlüssel erfolgt, was notwendig ist, damit nach
> der Änderung durch "insert ..." feststellbar wird, ob und welche
> Schlüssel sich verändert haben. Dies wird also abgefangen und
> damit ist auch eine berüchtigte Falle entfallen, in die jeder
> hoffnungsfrohe FLEX-Novize unweigerlich tappte.
>
> Abhilfe brächte nur, weil wir auf die genannte Funktionsweise nicht
> leichterdings wieder verzichten können, ein separater, anders
> heißender "find"-Befehl, der das besagte Schlüsselberechnen dann
> eben nicht durchführte. Der FLEXperte hätte dies dann zu wissen und
> anzuwenden, um an dieser Stelle nicht der Ihnen aufgefallenen
> Problematik aufzusitzen und ein Quentchen mehr Performanz zu erzielen.
Es geht ja nicht nur um die Schluesselberechnungen, wo das hier
auffiel: "Einen Satz in die Bearbeitung holen" ist ja von der
Realzeit her eine irrsinnig teure Aktion:
1. Der Satz muss gesperrt werden, dafuer muss Rueckgriff auf
Betriebssystemmechanismen (Range Locking) genommen werden, und
das womoeglich uebers Netzwerk
2. Bei der Schluesselberechnung erfolgen x Indexzugriffe, etwa
bei v14-Ersetzungen oder expliziten Nachladungen in den
Indexparametern
der zweite Punkt koennte mit ggfls. ausgefeilteren Mechanismen
zeitlich solange herausgezoegert werden, bis man es wirklich
braucht, also bis zum Put, das duerfte aber groessere interne
Umbauten erfordern, naemlich noch eine Datensatzkopie im
Hintergrund vorzuhalten.
Auch bei relationalen Datenbanken gibt es Locking-Mechanismen,
und bei jenen, die "Transaktionen" kennen, ist das wegen
des zusaetlichen Overheads etwas, das vom Client explizit
eingeschaltet werden muss...
Die Motivation der Angelegenheit erschliesst sich mir ausserdem
nicht:
1. Im Herbst ist die Heuristik "Sorry, jemand anderes war schneller"
verbessert worden, die schuetzt davor, unbeabsichtigt eine auf
einer veralteten Version eines Datensatzes beruhende Aenderung
in die Datenbank zurueckzuschreiben. Fuer "interaktive"
Bearbeitungen wie im a99-Kontext halte ich das fuer gut genug:
So ein Datenkonflikt ist immer auch ein Geschaeftsgangskonflikt
und es ist in Ordnung, wenn das intellektuell abgehandelt werden
muss.
Dementsprechend kommt a99 auch weiterhin ganz ohne Datensatzsperren
aus, man kann hunderte Saetze ungespeichert "in Bearbeitung" halten,
bei entsprechenden .ini-Einstellungen sogar tagelang. Das Risiko eines
zwischenzeitlichen Konflikts steigt dabei natuerlich gewaltig und
auch andere Effekte werden wichtig (ungespeicherte Aenderungen
sind ja nicht in der Datenbank sichtbar und koennen daher nicht auf
Indexierung und Anzeige spaeterer Datensaetze einwirken), aber
das deckt sich mit allgemeiner Computer-Lebensweisheit: Wer tagelang
sein Word-Dokument nicht speichert sollte sehr gut darueber
Bescheid wissen, wie hoch momentan die Gewitterhaeufigkeit ist
und welche USV er nutzt...
2. Bei gewissen Dingen, die im a99-Kontext etwa bei der Erwerbung
im Hintergrund ablaufen (Zaehler inkrementieren) oder beim klassischen
Update.exe (auch wenn das ueber acon realisiert wird) bzw. generell
im Zusammenhang mit "globalen Manipulationen" ist die Heuristik nicht
gut genug, insbesondere weil keine Gelegenheit besteht, den Benutzer
um Rat zu fragen oder weil ein "Rollback" mit automatisiertem Neuversuch
sehr aufwendig zu implementieren waere.
Charakteristisch hierfuer ist, dass ein Datensatz geholt wird,
automatisiert bearbeitet und sofort zurueckgespeichert. Und - man
denke an Zaehler - durchaus hochfrequent stets derselbe Datensatz.
Es hilft also nichts, den Konflikt beim Speichern zu erkennen, denn
dann ist es zu spaet: Der Konflikt muss von vorneherein ausgeschlossen
werden, dazu dient die Datensatzsperre und der Preis dafuer ist
abgesehen von Verarbeitungs- und Realzeit fuer die Sperroperationen
auch noch, dass der Mechanismus tendenziell unendlich lange stocken
kann, wenn anderswo durch eine Fehlfunktion eine Sperre haengen
geblieben ist.
Infrage kommen hierfuer gewisse nichtstandard Avanti-Jobs aus alter
Zeit (Mit avanti in die Datenbank schreiben ist traditionell keine
Standardfunktionalitaet und in den Interaktiven Faellen gibt es einen
Lese-Job, die Bearbeitung durch den Benutzer, dann einen Speicher-Job:
dafuer funktioniert ohnehin nur die Heuristik, da die Datensatz-sperren
nur innerhalb der Lebenszeit eines einzelnen Jobs gelten) sowie der
spezielle update.job.
3. Beim Bilden einer Ergebnismenge irgendwelche Saetze zu sperren
und auch noch deren Indexschluessel auf Verdacht hin auszurechnen
ist Viecherei. Viel der aktuellen Verwirrung hat moeglicherweise
mit der alten Verwirrung zu tun, dass nicht nur eine Ergebnismenge
gebildet wird, sondern auch deren erster Satz geladen wird bzw.
wenn sie nur einen Satz hat, wird der geladen und ueberhaupt keine
Ergebnismenge gebildet (m.W. vor einiger Zeit abgeschafft).
Aber auch beim expliziten Durchlaufen einer Ergebnismenge per Flex
gibt es keinen Grund fuer Datensatzsperren: Satz 1000 koennte
zwischenzeitlich geloescht worden sein, da hilft es mir aber auch
nichts, wenn ich ihn nach Verarbeitung von Satz 999 sperre, denn
da ist er bereits geloescht gewesen. Wir muessen davon ausgehen,
dass wir fuer Normaloperationen mit einer gewissen Unschaerfe
leben, bzw. wenn wir uns das nicht leisten koennen (wir also die
Version aller 1000 Saetze zum absolut identischen Zeitpunkt
benoetigen: -> Hotcopy, Backup) muessen wir explizit angemessen
heftige Locks setzen.
4. Die einzige Sperre, die bei lesender und schreibender
Normalverarbeitung benoetigt wird, ist eine interne fuer get
(und put): Auch wenn ein Datensatz auf der Platte ueber mehrere
Bloecke verteilt ist und das Betriebssystem daher mehrere
unabhaengige Lesezugriffe absetzen muss, muss "get" eine
integre Version zurueckliefern, nicht die erste Haelfte alt
und die zweite aus einer spaeteren Bearbeitungsstufe, die
zwischenzeitlich durch einen anderen Prozess / auf einem anderen
Arbeitsplatz zustandegekommen ist. Soweit ich weiss, sind
Probleme in dem Bereich noch nicht gemeldet worden, obwohl allegro
da keine Vorkehrungen trifft (diese waeren Locking von "Kacheln"
bzw. Repraesentanten davon mit Betriebssystem-Mitteln, wie es
m.W. bereits fuer die Lesezugriffe auf die Indexdatei erfolgt)
5. ein selbstgemachtes Problem ist, dass die Flex- und Jobbefehle
intern so realisiert sind, dass sie exakt einen Qualifier haben
koennen: Ich muss mich also zwischen
get first
und
get edit
entscheiden bzw. muss beides nacheinander notieren, obwohl ich
eigentlich ein kombiniertes
get edit first
meine...
>> ... zweitens sollten die Namensräume von Indexparameterdatei und
>> Exportskript nicht zusammengeworfen werden.
>
> Das war schon immer so (d.h. es wurde nichts, was voerher getrennt
> gewesen wäre, nun zusammengeworfen), hat seine Gründe und läßt
> sich nicht ändern. Es gibt auch Anwendungen, die genau dieses
> Feature nutzen.
Neu ist allerdings - als Antwort auf die spaeteren Mails - dass
bislang ein Export einfach so durchgerauscht ist, Interaktionen
mit den Variablen der Indexparameter waren in Anzeigeparametern
Thema, aber nicht in Exporten (bzw. nur dann, wenn sie in a99
oder PRESTO interaktiv zusammengestueckelt wurden).
viele Gruesse
Thomas Berger
Mehr Informationen über die Mailingliste Allegro