Announcement

Collapse
No announcement yet.

commit und Rollback zur rechten Zeit

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

  • commit und Rollback zur rechten Zeit

    Hallo,

    inzwischen hab ichs ja mit IB auch soweit verstanden, dass man dies mit
    Transaktionen macht.
    Transaktionen sollten ja auch nicht unbedingt zu lange gehen, deshalb habe
    ich in meiner Anwendung die Transaktion mit dem BeforePost-Ereigniss
    gestartet und mit dem after-Post Ereigniss beendet (commit bzw. RollBack)
    Jedoch erhalte ich die Meldung beim beim ersten Sprung in das
    BeforPostEreignis 'Transaktion ist aktiv', obwohl zu keinem Zeitpunkt zuvor
    diese Ereignisprozedur aufgerufen wurde (auch nicht getriggert, da ich hier
    einen breakpoint hineingesetzt habe)

    Nun meine Frage, wie macht Ihr das ?
    Startet da Delphi im Hintergrund noch irgendwelche Transaktionen schon
    automatisch, wenn edit, insert usw aufgerufen werden (TIbTable)?
    Gibt es nur die Moeglichkeit, die Transaktion vor dem Edit/Insert/Delete
    Aufruf zu starten ?

    Ciao

    Frank

  • #2
    Hallo,

    im Gegensatz zur BDE steht bei IBX der bequeme <i>AutoCommit</i>-Modus nicht zur Verfügung. Bei der BDE konnte man von der automatischen Steuerung auf die Handsteuerung umschalten, indem StartTransaction aufgerufen wurde. Bei IBX ist das nicht der Fall.

    Das Problem liegt darin, dass der InterBase erwartet, dass alle Zugriffe (auch SELECT-Abfrage) nur im Kontext einer <b>aktiven</b> Transaktion ausgeführt werden dürfen. Wenn TIBDataSet eine Datenmenge anzeigt, ist also bereits die InterBase-Transaktion aktiv, so dass das Veto bei <i>BeforePost</i> verständlich ist.

    Eine der Grundregeln in der C/S-Welt lautet, dass der Client niemals
    die Zeitdauer einer Transaktion bestimmen darf. Dabei muss der Entwickler gleich 2 Fälle betrachten:<br>
    a) Transaktionsdauer bei INSERT/UPDATE/DELETE (X-Locks)<br>
    b) Transaktionsdauer bei SELECT (S-Locks)<br>
    Die Schreibzugriffe verursachen ein X-Lock (Exklusive Sperre), daher
    muss die Zeitdauer dieser Sperre (= Gültigkeitsdauer der Transaktion)
    minimiert werden. Die Lesezugriffe verursachen ein S-Lock (Gemeinsame Sperre), wobei dank der Multigenerationenarchitektur des InterBase dies nicht so gravierende Folgen wie ein lange wirksamer X-Lock hat. Allerdings sollte auch hier die Zeitdauer der Transaktion so kurz wie möglich sein. Was bei der BDE kein Thema war (dank AUTOCOMMIT und der Intelligenz von TTable/TQuery), kommt bei IBX mit dem Dringlichkeitsvermerk auf die Tagesordnung. Bei IBX muss sich der Entwicklungs um alles selbst (!) kümmern, d.h. er hantiert direkt mit den InterBase-Transaktionen. Und da sogar ein einfacher Lesezugriff (SELECT) nur im Kontext einer Transaktion ausgeführt werden kann, gibt es ein Problem. Um dieses zu lösen, gibt es mehrere Möglichkeiten:

    a) Verzicht auf TDBGrid, Daten werden nur gelesen, in TEdits kopiert und danach die Transaktion über COMMIT beendet. IBX schliesst darauf alle aktiven Datenmengen (was hier nicht zum Problem wird).

    b) Verzicht auf TDBGrid kommt nicht in Frage, daher wird die Datenmenge sofort in eine In-Memory-Table (TClientDataSet, TIBClientDataSet oder ähnliches) kopiert und danach die Transaktion über COMMIT beendet. IBX schliesst darauf alle aktiven Datenmengen (was hier nicht zum Problem wird). Allerdings steigt der Aufwand, wenn die Daten auch editierbar sein sollen (Briefcase-Modell).

    c) Verzicht auf TDBGrid kommt nicht in Frage, Mehraufwand für In-Memory-Tabellen kommt nicht in Frage. In regelmässigen Abständen wird
    CommitRetaining aufgerufen - wobei IBX die Datenmenge offen hält und
    sich die aktuellen Datensatzposition nicht ändern. Vor dem Einsatz aber unbedingt den Beipackzettel mit den Risiken und Nebenwirkungen durchlesen.

    d) Verzicht auf TDBGrid kommt nicht in Frage, Mehraufwand für In-Memory-Tabellen kommt nicht in Frage. In regelmässigen Abständen wird
    Commit aufgerufen - wobei IBX die Datenmenge jedoch schließt. Wenn
    nach dem erneuten Öffnen der Datenmenge die "alte" Position sichtbar
    sein soll, muss dieser Datensatz vorher über ein eindeutiges Merkmal
    gespeichert werden.

    Die letzte Option könnt so aussehen:<br>
    1. TIBTransaction-Eigenschaft <b>IdleTimer</b>: Immer dann auf 10000 Millisekunden setzen, wenn die Datenmenge im State <i>dsBrowse</i> ist,anderenfalls den IdleTime über die Zuweisung von 0 deaktivieren<br>
    2. TIBTransaction-Eigenschaft <b>DefaultAction</b>: TACommit -> IBX schließt dabei automatisch alle zu diesem Zeitpunkt offenen Datenmengen, die dieser TIBTransaction-Instanz zugewiesen waren.<br>
    3. TIBTransaction-Ereignis <b>OnIdleTimer</b> auswerten: Datenmengen neu öffnen und alten Datensatz über die Primärschlüsselwerte suchen

    Im Ordner IBX ist ein Beispielprojekte (RedSys) zu finden, das diesen Weg demonstriert. Das Ganze wird ausführlicher in meinem Buch <i>InterBase Datenbankentwicklung mit Delphi</i> beschrieben (siehe Link im linken Frame)

    Comment


    • #3
      Hallo Andreas,

      vielen Dank fuer die ausführliche Antwort.
      Ich habs bei mir vorerst ueber cached-Updates geloest, die nur bei Insert/delete/update Anweisungen ausgeschaltet wird.
      Folgende Grundregel ist mir jedoch nicht so ganz klar :

      Eine der Grundregeln in der C/S-Welt lautet, dass der Client niemals die Zeitdauer einer Transaktion bestimmen darf

      Bzw. es wird ja bei der Anweisung
      StartTransaction
      Commit
      nicht die Zeitdauer (sounsoviel ms) vorgegeben sonder nur der Ablauf im Kontext des Client sortiert und ein commit wartet ja auch bis die Sache ausgefuehrt wird. Daher versteh ich nicht wieso dies 'haendisch' nicht zugelassen wird.

      Gruss
      Fran

      Comment


      • #4
        Hi,

        Wenn der Client eine Transaktion startet und Operationen ausführt, welche ein X-Lock zur Folge haben, muss es immer eine Art 'Notbremse' geben, die diese Sperre wieder aufhebt. Was machst du denn ( bzw. alle anderen Nutzer, die auf die gesperrten Daten zugreifen wollen ) wenn ein Mitarbeiter nach Start selbiger Transaktion für vier Wochen in den Urlaub geht und vergessen hat seinen Programm zu beenden ??

        Gruß
        Gesin

        Comment


        • #5
          Hallo Gesine,

          mit Client meine ich nicht den Benutzer sondern mein Programm.
          d.h der Benutzer drueckt auf einen Knopf, dadurch wird ein Methode aufgerufen in der wird eine Transaktion gestartet, Datensaetze editiert und zum Schluss die Transaktion wieder beendet (commit, bzw. Rollback wenn irgendwas schiefgeht)
          Soweit sogut.
          Probleme waeren jetzt noch theoretisch der Computer genau bei Ausfeuhren dieer Methode abstuerzen kann, ist dagegen imho nichts einzuwenden.
          Dann und nur dann muesste man von der Notbremse gebrauch machen (gibts da sowas wie ein timeout)
          Gruss
          Fran

          Comment

          Working...
          X