Announcement

Collapse
No announcement yet.

An Andreas Kosch/Interbase

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • An Andreas Kosch/Interbase

    Hallo Andreas,

    ich benötige beim InterBase folgendes Verhalten:

    Wenn eine Station einen Datensatz zur Bearbeitung aufruft, sollte dieser bis zum Speichern für andere
    Stationen nicht erreichbar sein - nach dem Speichern muß er aber sofort mit neustem Stand für alle
    Stationen wieder verfügbar sein (Dialogbuchhaltung).

    Mit den Standardeinstellungen (TRANSACTION) des InterBase 4/Linux ist so ein Verhalten nicht zur erreichen - oder?
    Ich habe auch versucht, mit "SET TRANSACTION ..." das Verhalten zu ändern - hier bekomme ich aber eine
    Fehlermeldung "nicht gestattet" - was das auch immer heißen mag?

    Jetzt ist es so, daß eine Station mit Commit oder Rollback ihre Aktionen bestätigen muß.
    Dadurch hat die andere Station aber noch nicht den neusten Stand der Daten wenn diese sich in der gleichen
    Tabelle befindet - erst wenn diese Station wiederum mit Commit ihre Änderungen
    bestätigt bzw. die Tabelle neu geöffnet wird, sind die aktuelle Daten vorhanden.

    Für mich ist es schwer nachzuvollziehen, was für ein Nährwert dieses Verhalten hat.

    Warum ist das Ganze mit "Versioning/Multigenerationenarchitektur" so kompliziert?
    Wenn Daten, die von einer Station bearbeitet werden, von einer anderen Station zur gleichen Zeit angefordert
    werden, muß dieses Station eine entsprechende Hinweis erhalten und nicht die Möglichkeit haben, ebenfalls eine
    Änderung an dieses Daten vorzunehmen.

    Jetzt werden Updates auf Datenbasis beim Start vorgenommen.
    Wenn zu Zeitpunkt des Starts ein Wert auf 10 steht und die Station 5 addiert, wie ist dann der Wert, wenn eine andere
    Station 3 addiert? Oder kann ich den InterBase so einstellen, das daß Versioning das hinkriegt. Dann habe ich aber
    immer noch das Problem, daß eine Station evtl. beim Start falsche Werte bekommt.

    Gruß
    Manfred Abeln

  • #2
    Hallo,

    das Versioning des InterBase lässt ich zu einem Satz verdichten: "Lesezugriffe behindern keine Schreibzugriffe und Schreibzugriffe behindern keine Lesezugriffe". In vielen Fällen ist das ein Segen (von dem andere SQL-Datenbanken nur träumen können), manchmal allerdings auch ein Fluch. Das in der Frage geschilderte Problem hat jedoch nichts mit dem InterBase zu tun und würde prinzipiell bei jeder SQL-Datenbank relevant werden. Nur die Details unterscheiden sich.

    Die zweite Grundregel beim InterBase lautet: "Ein Benutzer kann nur die Daten sehen, deren Transaktionsnummer niedriger ist als seine eigene". Damit legt der Zeitpunkt des Starts der eigenen Transaktion fest, welche Daten der Benutzer sehen kann. Dies ist kein Problem, wenn der Benutzer regelmässig eine neue Transaktion beginnt. Dies bedeutet jedoch auch, das eine ständig offene SELECT-Abfrage keine neuen Daten sehen kann. Werden aktuelle Daten benötigt, <b>muss</b> man eine neue Transaktion beginnen und als Folge davon auch die SELECT-Abfrage neu ausführen lassen.

    Im Gegensatz zu einer ISAM-Datenbank (dBASE, Paradox, ACCESS) arbeitet der Client einer SQL-Datenbank immer nur mit einer <b>Kopie</b> der Daten, niemals mit dem originalen Datensatz. Daher muss eine pessimistische Datensatzsperre auch logisch simuliert werden:

    1. Neue (explizite) Transaktion via TDatabase.StartTransaction beginnen

    2. Dummy-Update auf eine beliebige Tabellenspalte. Der InterBase "stempelt" die aktuelle Transaktionsnummer auf diesen Datensatz. Durch den Aufruf von StartTransaktion im Schritt 1 ist der AutoCommit-Modus der VCL deaktiviert, so das die Transaktion immer noch offen ist.

    3. Der Datensatz wird zur Bearbeitung eingelesen

    4. Der Benutzer bearbeitet den Datensatz

    5. Der Benutzer beendet seine Arbeit mit TDatabase.Commit.

    Wenn jeder diese Arbeitsschritte abarbeitet, erhält ein zweiter Benutzer bereits beim Schritt 2 das Veto des InterBase, wenn jemand anderer schneller war. Denn auch beim Versioning ist ein UPDATE auf eine offene Transaktion nicht zulässig - der Client kann in diesem Fall höchstens den letzten Commit-Zustand dieses Datensatzes (d.h. die vorletzte Version) auslesen (wenn er RECORD VERSION und NO WAIT verwendet).

    Was bedeutet das alles nun? Ich würde folgendes machen:

    a) TDatabase.TransIsolation = tiRepeatableRead verwenden (ist für den InterBase am effektivsten).

    b) Kurze, häufige Transaktionen (vor allem bei den Lesezugriffen) nutzen. Nicht ohne Grund verwendet die VCL den AutoCommit-Modus, der diese Forderung implizit einhält.

    c) Falls es nicht anders geht, alle Clients über InterBase-Events von Änderungen an einer Tabelle (ausgelöst über Trigger) benachrichtigen lassen.

    Aus gutem Grund befasst sich in meinem Buch <b>Client/Server Datenbankentwicklung</b> ein ganzes Kapitel auf fast 60 Seiten mit dem Thema Mehrbenutzerzugriff.
    &#10

    Comment


    • #3
      Hallo Andreas,

      danke für deine Nachricht.

      Ich arbeite mit IBDatabse, IBTransaction, IBTable usw. und IBDatabase.TransIsolation gibt es nicht?

      In meiner ersten Testversion meines Programms hatte ich vor jedem Lesen eine neue Transaction gestartet und nach erfolgreichen Speichern mit Commit bestätigt. Nach einem Commit war dann auch IBTable geschlossen und mußte ebenfalls neu geöffnet werden. Trotz dieser
      Vorgehensweise waren auf der 2. Station die aktuelle Daten nicht sichtbar. Muß auch noch IBDatabase.Connect auf False
      gesetzt werden?

      Bei dieser Vorgehensweise wird der Dialog doch sehr langsam.
      Wenn nun weitere Tabelle hinzukommen (wie es in einer Buchhaltung/Kassenanbindung und Lagerverwaltung der Fall ist),
      bekomme ich wahrscheinlich (mal von Handling abgesehen) ein großen Geschwindigkeitsproblem und irgendwann soll das Programm auch mal fertig werden.

      Wie und wo setzt man denn den "Transaction Isolation Level"?
      Über ExecSQL bekomme ich eine dümmliche Fehlermeldung: "nicht gestattet"

      Übriges - dein Buch habe ich mir am Wochenende in Teilen durchgelesen

      Gruß
      Manfre

      Comment


      • #4
        Hallo,

        der Hinweis auf <b>IBX</b> fehlte leider in der Frage. IBX ändert natürlich vieles - wobei nicht alle Änderungen positiv sind. Alle fürsorglichen Hilfen der BDE und der VCL (die vieles implizit im Hintergrund erledigt haben) stehen mit IBX nicht zur Verfügung, so dass der Entwickler selbst für die notwendigen Aufrufe verantwortlich ist. Jemand, der mit IBX seine erste C/S-Anwendung entwickelt, hat sich den schwersten Brocken an den Hals gehängt, der im Delphi-Paket zu finden ist ;-)

        Mit einem Doppelklick auf die <b>TIBTransaction</b>-Instanz wird der <b>Transaktions-Editor</b> aufgerufen und dort kann man über die 4 Radiobutton die Transaction Isolation Level auswählen.

        Wenn Benutzer A nach seiner Änderung zum Beispiel in der Ereignisbehandlungsmethode für das AfterPost-Ereignis den Aufruf von IBTable1.Transaction.Commit absetzt, wird die aktuelle Transaktion abgeschlossen. Somit kann jeder Benutzer die geänderten Daten sehen, dessen eigene Transaktionsnummer höher ist als die vom Benutzer A beim Commit-Aufruf verwendete Transaktionsnummer. Somit muss Benutzer B seine SELECT-Abfrage neu ausführen bzw. seine TIBTable-Instanz neu öffnen, wenn er die Änderungen vom Benutzer A sehen will. In einer typischen C/S-Anwendung gibt es keine DBGrid-Darstellung zum Browsen im Datenbestand, sondern der Anwender fordert immer nur <b>einen</b> Datensatz zur Bearbeitung/Anzeige an. Bei diesem Design ergeben sich die ständig neuen (aktuellen) Transaktionsnummern automatisch, so das jeder Benutzer immer den aktuellsten Inhalt seines Datensatzes sieht.

        Aufgrund des völlig anderen Funktionsprinzips von SQL-Datenbanken sehen C/S-Anwendungen eben anders aus und funktionieren auch anders als eine dBASE/Paradox/ACCESS-Anwendung. Somit wird man unabhängig von IBX oder BDE immer dann Schiffbruch erleiden, wenn man diese Besonderheiten beim eigenen Design der Benutzeroberfläche nicht berücksichtigt

        Comment

        Working...
        X