Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Datenbanken (https://www.delphipraxis.net/15-datenbanken/)
-   -   Delphi Lockmode bei Updates (https://www.delphipraxis.net/17332-lockmode-bei-updates.html)

Wegalt 3. Mär 2004 13:45


Lockmode bei Updates
 
Hallo,

ich möchte ein Update absetzen, ohne das der Datensatz der upgedatet wird gespert wird.

Im Moment sieht das so aus!
SQL-Code:
        Table.Lockmode := lmNone;
        Table.KeyFields := 'SOURCEID';
        Table.FilterSQL := 'Filename = ''' + PDSFName + '''';
        Table.Open;
        Table.Edit;
        Table.FieldByName('EQUIPMENTID').AsString := EquipmentID;
        Table.POST;
Wenn die Verbindung jetzt vor dem Commit abreißt und ich dann das gleiche Update mit einer neuen Session absetzte, muß ich warten, bis die alte Session gekillt wurde.
Obwohl ich Lockmode := lmNone gesetzt habe.

Ich nutze
Oracle8i Enterprise Edition Release 8.1.6.0.0
und Odac 4.5

Ich hoffe ihr könnt mir helfen

Gruß
Wegalt

Robert_G 3. Mär 2004 17:19

Re: Lockmode bei Updates
 
Du kannst doch mit den ODAC-Kompos auch anonyme Blöcke absetzen, oder?
Ich habe mir die ODAC noch nicht angeschaut (sollen ja ganz gut sein...), so würde es mit Direct Oracle Access aussehen:

Dadurch schickst du alles in einem Stück an den Server. Transaktions- & Fehlerhandling wird er dann übernehmen.
Bei einem Fehler gibt es ein Rollback, die Fehlermeldung steht dann in ErrorStr.

Delphi-Quellcode:
Var
  ErrorStr                               : String;
Begin
  With OracleQuery Do
  Begin
    SQL.Text :=
      'Begin' + #10 +
      '  Update DeineTabelle' + #10 +
      '  Set   EquipmentID = :i_EquipID' + #10 +
      '  WHERE FileName   = :i_FileName;' + #10 +
      '' + #10 +
      '  Commit;' + #10 +
      'Exception' + #10 +
      '  When Others Then' + #10 +
      '     Rollback;' + #10 +
      '     :o_Errors := Sqlerrm;' + #10 +
      'End;';
    If Variables.Count = 0 Then
    Begin
      DeclareVariable('i_EquipID', otInteger);
      DeclareVariable('i_FileName', otString);
      DeclareVariable('o_Errors', otString);
    End;

    SetVariable('i_FileName', PDSFName);
    SetVariable('i_EquipID', EquipmentID);
    Execute;

    ErrorStr := GetVAriable('o_Errors');
  End;
  MessageDlg(ErrorStr, mtError, [mbOK], 0);

End;

Wegalt 3. Mär 2004 19:07

Re: Lockmode bei Updates
 
Also erstmal danke für deinen Vorschlag, da ich aber in mehere Tabelle etwas einzutragen oder zu updaten habe ist das leider nicht ganz meine Lösung. Commit will ich nur absetzen wenn alles geklappt hat(einige Exceptions wären sogar erlaubt)

Damit will ich mir das Löschen sparen wenn etwas nicht so ganz passt.


Ich habe mich mal schlau gemach und soetwas wie dieses..

SQL-Code:
UPDATE Users WITH (NOLOCK)
SET Username = 'fred' WHERE Username = 'foobar'
..kann ich leider nicht benutzen. Oracle speert die Datensätze automatisch. Weiß nicht wo das geht?!

Irgendwie soll das mit DBMS_PIPE gehen. Sich mit der neuen Session (nach Verbindungsabbruch)
mit DBMS_PIPE auf die alte Session connecten und diese schließen.

Leider kann ich auch dieses..
Delphi-Quellcode:
   
OraSQL1.SQL.Text := 'alter system kill session ''' + slSidSerial[i] + '''';
OraSQL1.Execute;
..nicht nutzen, da ich keine Systemrechte habe.


Also wenn dir(euch) doch noch was einfällt?!

Gruß
Wegalt

Robert_G 3. Mär 2004 19:43

Re: Lockmode bei Updates
 
kill session ist keine gute Idee. Es kann vorkammen, dass eine session im Status "marked for kill" mehrere Stunden verbleibt (vor allem bei der 8.16).
Du kannst alle deine Updates in einen Block packen. Die effektive Zeit, die die Aktionen dann benötigen wird < 0,Irgendwas Sek. betragen.
In dieser Zeit kann die Tabelle für Schreibrechte doch gesperrt sein.
Gebe mir mal ein Beispiel, vielleicht kommen wir dann zu einer Lösung.

Wegalt 4. Mär 2004 14:13

Re: Lockmode bei Updates
 
Das es nicht so klasse ist die session zu killen hab ich schon gemerkt. Nach einer gewissen Zeit konnte sich keiner mehr an die DB anmelden weil zu viele Prozesse liefen. Es dauerte die ganze Nacht bis man die DB wieder vernünftig benutzen konnte.

Ich denke du hast mich überzeugt alles in einem Block abzuschicken. Ich habe ca 80 Selects die ich vorher absetzen muss. Dann würden entweder 130 bis 500 Inserts oder Updates abgesetzt werden. Ich denke mal das ich so viele Statemants mit einem Block absetzen kann wie ich will!?!

Zwar wird die Fehlerbehandlung dann etwas schwerer ( z.B. soll er manchmal ein Statemant einfach überspringen, wenn eine Spalte nicht existiert) aber trotsdem machbar. Außerdem müßte ich wissen, ob alles geinsertet wurde. Um entgültig sicher zu sein müßte ein einziges Kontrollstatement abgesetzt werden und das auch nur wenn die Verbindung während der Transaktion abreißt. Ist es auch möglich sich mehere Exceptionmeldungen wieder geben zu lassen?

Gruß
Wegalt

Robert_G 4. Mär 2004 14:49

Re: Lockmode bei Updates
 
Das wäre ein anonymer Block, der in einen Tabelle ein INSERT vornimmt und dir als Ouputvariable ein PseudoLog und die Anzahl der Fehler meldet (hier kann es ja nur max einer sein).

SQL-Code:
Declare
  RowsProcessed Number(6);
Begin
  :o_Log     := Null;
  :o_ErrCount := 0;
  -- Hier beginn ein Unterblock
  Begin
    :o_Log := :o_Log || chr(10) || 'Test_Tab1 (INSERT):';
 
    Insert INTO Sheme0815.Test_Tab1 t
      (t.Text)
    VALUES
      (:i_NewText);
 
    -- da INSERTs implizierte cursor öffnen bekommst du mit...
    RowsProcessed := Sql%Rowcount;
    --  die Anzahl der Einträge die eingefügt/gelöscht/geändert wurden
    :o_Log := :o_Log || chr(10) || ' ' || RowsProcessed ||
              ' record(s) inserted...';
 
    -- Exception handling des Unterblock
 
  Exception
    When Others Then
      RowsProcessed := 0;
      :o_Log       := :o_Log || chr(10) || --
                       ' ' || Replace(Sqlerrm, chr(10), chr(10) || ' ');
      :o_ErrCount  := :o_ErrCount + 1;
      /* Das formatiert die Fehlermeldungen á la:
      Test_Tab1 (INSERT):
        ORA-01722: invalid number
      */
 
    -- Ende des Unterblock
  End;

  :o_Log := SubSTR(:o_Log, 2);
End;

Robert_G 4. Mär 2004 15:28

Re: Lockmode bei Updates
 
Bei mehreren INSERT pro Tabelle würde ich dir BULK SQL empfehlen.
:NewText wäre eine Index-By-Table, die als Variable an das Statement übergeben wurde.

SQL-Code:
FORALL i IN :NewText.First..:NewText.Last
   INSERT INTO Test_Table VALUES (:NewText(i));
Der Performancegewinn bei Bulk-SQL ist enorm -> bis zu 30-fache Geschwindigkeit gegenüber normaler DML.

Du kannst in einem anon. Block IMHO 128.000 Zeichen verwenden. Da passen also eine Menge Statements rein!


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:33 Uhr.

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz