![]() |
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:
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.
Table.Lockmode := lmNone;
Table.KeyFields := 'SOURCEID'; Table.FilterSQL := 'Filename = ''' + PDSFName + ''''; Table.Open; Table.Edit; Table.FieldByName('EQUIPMENTID').AsString := EquipmentID; Table.POST; 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 |
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; |
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:
..kann ich leider nicht benutzen. Oracle speert die Datensätze automatisch. Weiß nicht wo das geht?!
UPDATE Users WITH (NOLOCK)
SET Username = 'fred' WHERE Username = 'foobar' 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:
..nicht nutzen, da ich keine Systemrechte habe.OraSQL1.SQL.Text := 'alter system kill session ''' + slSidSerial[i] + ''''; OraSQL1.Execute; Also wenn dir(euch) doch noch was einfällt?! Gruß Wegalt |
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. |
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 |
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; |
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:
Der Performancegewinn bei Bulk-SQL ist enorm -> bis zu 30-fache Geschwindigkeit gegenüber normaler DML.
FORALL i IN :NewText.First..:NewText.Last
INSERT INTO Test_Table VALUES (:NewText(i)); 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