Announcement

Collapse
No announcement yet.

D5/DAO35 - Probl. beim Schreiben von Transaktionen (Commit)

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

  • D5/DAO35 - Probl. beim Schreiben von Transaktionen (Commit)

    Delphi 5 / MSACCESS-DAO35 <br>
    Problem beim Schreiben von Transaktionen (Commit) <br>
    ----------------------------------------------------<br>
    Hallo Herr Kosch, <br>

    ich verwende die MSACCESS-DAO in einer Mehrbenutzerumgebung. (DAO soll's aus diversen Gruenden auch erstmal bleiben!!)
    Da DAO35 nicht auf Satzebene, sondern nur auf Seitenebene sperrt, habe ich ein passendes Feld "Sperre" in meine Datenstruktur integriert. Der Ablauf ist nun ziemlich simpel: ich sperre mir zunaechst einen Datensatz wie folgt, wobei bei einer erfolgreichen Sperre die Variable Zugriff auf true gesetzt wuerde... <br>
    <br>

    Zugriff:= false; <br>
    Database1.TransIsolation:= tiRepeatableRead; <br>
    Table1.Refresh; <br>
    Table1.FindKey([IndexNo]); <br>
    if Table1Sperre.AsInteger = 0 then begin // wenn Datensatz frei<br>
    &nbsp; &nbsp; Database1.StartTransaction; <br>
    &nbsp; &nbsp; try // versuche, Sperre zu schreiben<br>
    &nbsp; &nbsp; &nbsp; &nbsp; Table1.Edit; <br>
    &nbsp; &nbsp; &nbsp; &nbsp; Table1Sperre.AsInteger:= 1; <br>
    &nbsp; &nbsp; &nbsp; &nbsp; Table1.Post<br>
    &nbsp; &nbsp; except<br>
    &nbsp; &nbsp; &nbsp; &nbsp; Table1.Cancel; <br>
    &nbsp; &nbsp; end; <br>
    &nbsp; &nbsp; Table1.FlushBuffers; // (versuche) Schreiben erzwingen... <br>
    &nbsp; &nbsp; DBISaveChanges(Table1.Handle); <br>
    &nbsp; &nbsp; Database1.Commit; // ---> schreibts hier wirklich physikalisch ? <br>
    &nbsp; &nbsp; Sleep(1000); // Warten, falls irgendwer im Netz schneller war<br>
    &nbsp; &nbsp; Application.Processmessages; <br>
    &nbsp; &nbsp; Table1.Refresh; // Daten nochmal laden<br>
    &nbsp; &nbsp; Table1.FindKey([IndexNo]); <br>
    &nbsp; &nbsp; if Table1Sperre.AsInteger = 1 then // Sperre wirklich geschrieben? &nbsp; &nbsp; <br>
    &nbsp; &nbsp; &nbsp; &nbsp; Zugriff:= true; <br>
    end; <br>
    <br>

    Dann lade ich mir alle Daten lokal, d.h. in nicht-datensensitive Komponenten, kann dann beliebig lange daran arbeiten und speichere die Daten wieder in einer Transaktion in die Datenbank und setze in einer weiteren Transaktion die Sperre wieder zurueck. <br>
    <br>
    Nun habe ich das Problem, dass gelegentlich trotzdem gleiche Datensaetze von verschiedenen Usern gesperrt werden koennen. Daher warte ich ja auch nach einem scheinbar erfolgreichen Schreibvorgang eine Sekunde und schaue dann nach, ob die Sperre noch steht – und erst dann gehe ich davon aus, dass die Sperre gesetzt wurde. Intensive Tests (mit sehr wenig Datensaetzen) haben ergeben, dass die Sache 99 mal funktioniert, aber eben beim 100. mal NICHT. Logischerweise ergab eine Erhöhung der Wartezeit (die ja nervt) eine Verbesserung, aber leider keine absolute Sicherheit. <br>
    <br>
    <b>FAZIT</b>: Nun sind habe ich doch Zweifel, ob mit dem Database1.Commit wirklich immer alles sofort physikalisch gespeichert wird...! Und siehe da, in der Doku DAO35.HLP habe ich unter der zugehoerigen Methode "CommitTrans" folgenden Hinweise gefunden: "...In einem Microsoft Jet-Arbeitsbereich kann die Konstante dbFlushOSCacheWrites zusammen mit CommitTrans angegeben werden. Dadurch wird erzwungen, dass das Datenbankmodul alle Aktualisierungen sofort auf den Datentraeger schreibt, anstatt zuerst in den Cache zu speichern..." <br>
    <br>
    Meine Frage ist nun, ob beim Aufruf von Database1.Commit mit "dbFlushOSCacheWrites" sofort geschrieben wird – und wenn nicht, wie kann ich das erzwingen? In der RTL-Source habe ich nichts gefunden. Falls ich in der Loesung direkt auf die DAO zugreifen muß, waere ich dankbar, wenn Sie mir aufzeigen wuerden, wie das Code-technisch ca. auszusehen hat... <br>
    <br>
    Mit freundlichem Gruss<br>
    <br>
    Dipl.-Inform. Christian Oestmann<br>
    <br>

  • #2
    Also zu dem Code gibts schon ein paar Anhaltspunkte:<br>
    Die BDE hat ja ihre eigenen Sessions, die dann mit der notwendigen OLE-Einbindung synchronisiert werden müssten. Das wird wohl schwierig weil da ja Handles und Objekte verbunden werden müssen.<br>
    Und zu dem "dbFlushOSCacheWrites" kann ich sagen, dass ich ziemlich sicher vermute, dass der Native-ACCESS treiber diesen Parameter nicht verwendet und aus Performance-Gründen die Schreibvorgänge über Cache laufen läßt. Ist der Zugriff vielleicht in der Treiber-DLL hartkodiert ?<p>
    Also wenn mir hier ein Experte weiter helfen könnte.... wäre toll, sonst kann ich - wegen diesem kleinen Grund - ja im Prinzip den ganzen DAO-Kram vergessen

    Comment


    • #3
      Hallo,

      da muss ich passen - DAO war vor meiner Zeit ;-)

      Im Fall vom DAO-Nachfolger ADO hat Microsoft über die JRO-Objekte einen anderen Weg vorgesehen, um den lokalen Schreibcache der Jet Engine sofort zurückschreiben zu lassen:
      <pre>
      uses JRO_TLB, ADOInt, ADODB_TLB;

      procedure TForm1.Button1Click(Sender: TObject);
      var
      aJet : IJetEngine;
      aConn : _Connection;
      begin
      ADOConnection1.Connected := True;
      aJet := CoJetEngine.Create;
      aConn := ADODB_TLB._Connection(ADOConnection1.ConnectionObj ect);
      aJet.RefreshCache(ADODB_TLB._Connection(aConn));
      StatusBar1.SimpleText := 'RefreshCache erfolgreich aufgerufen.';
      end;
      </pre&gt

      Comment

      Working...
      X