Danke im Voraus,
Katharina
mit DAO sind IMHO verschachtelte Transaktionen nur mit der Jet-Engine
möglich, d.h. mit BeginTrans, CommitTrans und Rollback, bei ODBC geht nur
eine Ebene.
Tschüß
Frank
Katharina schrieb in Nachricht <37e1...@news.farside.net>...
>Umstellen einer sehr umfangreichen VB6-Applikation, die bisher Access als
DB
>benutzt, auf Oracle.
>Serverzugriffe laufen über DAO/Jet-Engine/ODBC/PassThrough.
>Alles läuft wunderbar, das einzige Problem ist zur Zeit noch folgendes:
>Auf diese Art sind geschachtelte Transaktionen nicht möglich, bei der
>zweiten kommt immer "SET TRANSACTION muss erste Anweisung sein."
schnipp
>Wie lassen sich geschachtelte Transaktionen per DAO verwirklichen?
schnapp
das kann ich nicht so stehen lassen, denn der Transactionsmechanismuß hat
doch nichts mit ODBC zu tun, ODBC löst den nur aus, die Datenbank verwaltet
den in Rollback-Segmenten.
Die Anzahl der Transaktionen werden von dem verwendeten Betriebssystem und
der Rollbacksegmentgröße bestimmt. (sind aber > als 100 schon im
Default-Zustand)
Beim Rückgängigmachen (Rollback) einer Transaktion werden alle !!!
Änderungen die bis zu diesem Zeitpunkt in der Transaktion hängen rückgängig
gemacht. Nun können für lange Transaktionen die mehrere SQL-Anweisungen
enthalten können "Savepoints" gesetzt werden, um eben diese Transaktion in
kleinere Einheiten zu unterteilen.
Somit ist es bei einer Oracle Datenbank also möglich entweder eine
Transaction komplett rückgängig zu machen oder auch nur bis zu einem
bestimmten "Savepoint".
Um mit "Rollback-Mechanismen" zu arbeiten gehört jedoch ein ausgefeiltes
Transaktionsmanagement, um die Integrität der Daten sicherzustellen, dazu.
(Sollte also wohl durchdacht sein).
sollte dies nicht Ausreichen stehe ich gerne für weitere Erklärungen zur
Verfügung.
Desweiteren würde ich empfehlen nicht mit dem "DAO-Geraffels" auf eine
Oracle-DB zuzugreifen.
Gruß Carl
ich arbeite auch mit einer Oracle Datenbank (auf UNIX) und mit DAO auf dem PC. Was mir etwas Kopfzerbrechen bereitet ist das "Passthrough"! Unter VB3 war "Passthrough" beim Lesen von Daten noch schneller, beim Schreiben allerdings nicht so flexibel.
Seit VB4 hat sich das ganze geändert. Bei internen Tests haben wir festgestellt, daß eingebundene Tabellen (Access-MDB´s) und DAO auch beim Lesen mindestens genauso schnell ist wie "Passthrough". DAO bzw. Jet optimiert da anscheinend ein bißchen.... (man kanns kaum glauben!)
Worauf ich hinaus will: Es lohnt sich nicht, den Weg über "Passthrough" zu gehen und ich könnte wetten, daß genau bei solchen Aktionen der beschriebene Fehler auftritt.
Falls es das nicht ist, könnte auch der ODBC Treiber der Übeltäter sein! Der ODBC Treiber muß die geschachtelten Transaktionen unterstützen. Nachdem Jet das kann und Oracle das kann bleibt noch der ODBC Treiber als Bindeglied. Und wenn der das nicht kann nützt alles nix.... (Die Erfahrung habe ich mit Resultsets vom Typ "dynamic" gemacht! Aber das ist eine andere Geschichte.)
Hoffe es hilft
Eddie
Katharina <Entwi...@LoyHutz.de> schrieb in im Newsbeitrag: 37e1...@news.farside.net...
> Hallo!
> Ich habe gerade ein fast fertiges Projekt übernommen:
> Umstellen einer sehr umfangreichen VB6-Applikation, die bisher Access als DB
> benutzt, auf Oracle.
> Serverzugriffe laufen über DAO/Jet-Engine/ODBC/PassThrough.
> Alles läuft wunderbar, das einzige Problem ist zur Zeit noch folgendes:
> Auf diese Art sind geschachtelte Transaktionen nicht möglich, bei der
> zweiten kommt immer "SET TRANSACTION muss erste Anweisung sein."
> Habe nun versucht, das unter Umgehung der Jet-Engine per DAO/ODBCDirect zu
> machen, selbes Ergebnis.
> Auch ein kleines Testprogramm, in dem ich das mit ADO probierte, scheiterte.
> Da ich noch nicht so reich an Erfahrungen auf diesem Gebiet bin, dachte ich,
> ich frage mal nach:
> Wie lassen sich geschachtelte Transaktionen per DAO verwirklichen?
>Falls es das nicht ist, könnte auch der ODBC Treiber der Übeltäter sein!
Der ODBC Treiber muß die geschachtelten Transaktionen unterstützen.
>Nachdem Jet das kann und Oracle das kann bleibt noch der ODBC Treiber als
Bindeglied. Und wenn der das nicht kann nützt alles nix.
DA HAST DU WAR,
M$ und Oracle ist die absolte Haß-Liebe.
Mal ist der ODBC-Treiber einwandfrei, das nächste mal liefert M$ in garnicht
erst aus.
Bei uns fahren wir den Intersolv (?)-Treiber für Oracle.
Tschüß Carsten
bevor jetzt der Thread noch länger wird.
Zunächst geht es um die Fehlermeldung "SET TRANSACTION muss erste Anweisung
sein."
die Katharina hatte.
Diese Fehlermeldung ist ganz normal und hat nichts mit Treibern oder
ähnlichem zu tun.
(Der Treiber muß nur die Funktion unterstützen mehr nicht, hat er diese
nicht, wäre die Fehlermeldung ne andere)
Unabhängig der Datenzugriffsmethode (ADO/DAO/RDO usw.) ist es bei RDBS
üblich bei verändernden Datenzugriffen (Insert,Update,Delete) Transaktionen
zu schreiben und dies ist !!!ausschliesslich !!! Sache des verwendeten RDBMS
und nicht irgendwelcher Treiber (bei DAO gibt es 2 Wege, dazu gleich mehr).
Grundsätzlich:
Erst das Festschreiben ("COMMIT") einer Transaktion macht Änderungen, die
sich als Gesamt-Ergebnis aller ändernden SQL-Statements in dieser
Transaktion befinden, für all diejenigen Transaktionen andere
Benutzer-Sessions sichtbar (erst ab hier kann man selbst und andere die
Änderung sehen).
Daher folgendes:
Üblicherweise ist die "DEFAULT"-Einstellung der jeweils benutzten
Datenzugriffs-Methode, nach jedem ändernden Zugriff ein "COMMIT" abzusetzen
und zwar deswegen weil von vornherein keine Transaktion angestossen wird.
Damit sind die geänderten Daten in euren Anwendungen auch gleich sichtbar.
Wenn jetzt versucht wird, eine Transaktion rückgängig (Rollback) zu machen
erscheint die Fehlermeldung:
"SET TRANSACTION muss erste Anweisung sein."
ist auch logisch, denn was soll Rückgängig gemacht werden, wo doch zuvor
ein "COMMIT" abgesetzt wurde und sich daher nichts in der Transaktion
befindet.
Dies bedeutet:
1. Transaktion öffnen
2. SQL-Statement ausführen
3. bei fehlschlagen des Statements Rollback ausführen
4. mittels "COMMIT" Transaktion schliessen. (ab hier werden geänderte Daten
sichtbar)
Ich hoffe das hilft soweit.
Nun zu DAO/RDBMS
Da von Performance zu reden geht nur nach dem Motto: auch ne Schnecke ist
schnell, wenn man sie mit etwas langsamerem vergleicht.
(Wie kann man eine Isam-Basierende Zugriffsmethode (DAO/Jet-Engine) als
Performant bezeichnen die für relationale Datenmengen nicht gebaut wurde.)
DAO ist eine Hight-Level API die insbesondere für Zugriffe auf die
Jet-Engine (ISAM-Basierend) gebaut wurde, darüberhinaus wurden wohl von MS
in Ermangelung anderer High-Level-API's noch ODBCDirect eingebaut.
Das muß man sich mal auf der Zunge zergehen lassen, und dann nochmal über
Performance nachdenken :-)).
Ich selbst programmiere jetzt etwa 5 Jahre mit Oracle-DB's, als DAO kam
einen Blick riskiert verworfen und mit der Low-Level-API "ODBC" weiter
gemacht. War die beste Entscheidung.
Heute benutze ich in zunehmenden Maße ADO oder OLE-DB und kann mich (bis
jetzt) nicht beklagen, ist ne tolle und sehr mächtige Sache.
Ich möchte mit dem hier Geschriebenen niemanden Beleidigen und erhebe auch
nicht den Anspruch der Vollständigkeit, dazu wären Bücher notwendig, stehe
aber für weitere Hilfen gerne zur Verfügung.
Gruß Carl
OK, es gibt einige Ausnahmen, bei denen sich Passthrough doch noch lohnt. Aber nach meiner Erfahrung sind das dann Abfragen, die man in Access sowieso nicht formulieren kann, z.B. weil Access den Befehl decode() nicht versteht, oder man durch umstellen des SQL-Statements Oracle veranlassen will gewisse Indizes zu verwenden damit das ganze etwas flotter geht..... Aber das sind wirklich die Ausnahmen.
Und was den Intersolv Treiber angeht: Den verwenden wir auch! Laut meinem Kenntnisstand gibt es momentan keinen besseren!
Ciao
Eddie
Carsten Sekulla <carsten...@medizin.uni-halle.de> schrieb in im Newsbeitrag: uJl2pVbA$GA....@cppssbbsa02.microsoft.com...
Carl Kampwerth <induc...@csi.com> schrieb in im Newsbeitrag: O6z9$PcA$GA.197@cppssbbsa03...
Tja, manchmal muß man ein Posting halt nur *richtig* durchlesen. Da hast Du wohl recht!
>
> Ich hoffe das hilft soweit.
>
> Nun zu DAO/RDBMS
> Da von Performance zu reden geht nur nach dem Motto: auch ne Schnecke ist
> schnell, wenn man sie mit etwas langsamerem vergleicht.
Stimmt!
> (Wie kann man eine Isam-Basierende Zugriffsmethode (DAO/Jet-Engine) als
> Performant bezeichnen die für relationale Datenmengen nicht gebaut wurde.)
> DAO ist eine Hight-Level API die insbesondere für Zugriffe auf die
> Jet-Engine (ISAM-Basierend) gebaut wurde, darüberhinaus wurden wohl von MS
> in Ermangelung anderer High-Level-API's noch ODBCDirect eingebaut.
Dadurch wird es aber auch nicht schneller!
> Das muß man sich mal auf der Zunge zergehen lassen, und dann nochmal über
> Performance nachdenken :-)).
>
Besser es funktioniert, als das es gar nicht funktioniert!
> Ich selbst programmiere jetzt etwa 5 Jahre mit Oracle-DB's, als DAO kam
> einen Blick riskiert verworfen und mit der Low-Level-API "ODBC" weiter
> gemacht. War die beste Entscheidung.
> Heute benutze ich in zunehmenden Maße ADO oder OLE-DB und kann mich (bis
> jetzt) nicht beklagen, ist ne tolle und sehr mächtige Sache.
>
Das finde ich auch, hatte allerdings noch keine Gelegenheit, mich näher damit zu befassen. Könntest Du mir mal (per Mail) mitteilen, mit welcher Version und in welchem Umfang Du damit arbeitest? Allgemeine Angaben würden mir auch reichen... Thanks!
> Ich möchte mit dem hier Geschriebenen niemanden Beleidigen und erhebe auch
> nicht den Anspruch der Vollständigkeit, dazu wären Bücher notwendig, stehe
> aber für weitere Hilfen gerne zur Verfügung.
>
> Gruß Carl
>
>
Niemand ist hier beleidigt! Für den Info-Tausch sind diese Groups doch da!
Gruß Eddie
Katharina
entweder im Datenbank oder Workspace "BeginTrans" damit hebst du die
automatische "Commit"-Function auf
anschliessend mit der Execute-Methode folgendes Schema durchführen
dao.sql ="savepoint spoint1"
Execute
dao.sql="update tab1 set sp1=sp2"
Execute
dao.sql="savepoint spoint2"
Execute
dao.sql="update tab2 set sp1=sp2"
Execute
dao.sql="Rollback to savepoint spoint2" (hier nur bis Spoint2)
Execute
oder "Rollback to savepoint spoint1" (hier würde alles Rückgängig gemacht
werden)
Execute
(Und das hat mit dem Treiber nichts zu tun)
Somit kannst du von "Savepoint zu Savepoint" deine Transaktionen rückgängig
machen.
Du mußt allerdings unbedingt nach den geglückten Statements auch ein
"Commit" durchführen da sonst keine Daten festgeschrieben sind und deine
Änderungen beim Ausloggen verloren gehen.
Und denke daran erst bei einem "Commit" bekommen andere User-Sessions und
dein User selbst gie geänderten Daten zu sehen.
Im übrigen benutze ich seit Ora 6 die Oracle-Odbc-Treiber (allerdings nicht
mit DAO) und der Transactions-Mechanismuss hat bisher immer funktioniert.
Ich hoffe jetzt, dass es hilft. :-)
Gruß Carl
Das hilft mir schonmal sehr, Danke! Werd's ausprobieren.
Noch eine Nachfrage habe ich: Wie bestätige ich denn dann bis zu einem
Savepoint? Geht das überhaupt? Denn in Access geht es wohl, eine innere
Transaktion einzeln mit Commit zu bestätigen, in der Orahilfe habe ich aber
in der Syntax für COMMIT kein "TO savepointxyz" gefunden.
Katharina
Carl Kampwerth schrieb in Nachricht <#ward0EB$GA.249@cppssbbsa03>...
Option Explicit
DefInt A-Z
Option Compare Text
Dim mDB As Database
Dim mRS As Recordset
Private Sub cmdCommand_Click(Index As Integer)
Select Case Index
Case 0 'access
Set mDB = OpenDatabase("C:\VB6\Entwicklung\vFM70\Daten\Freiburg.mdb")
Workspaces(0).BeginTrans
mDB.Execute "INSERT INTO tblTEST VALUES('Wert1');"
Workspaces(0).BeginTrans
mDB.Execute "INSERT INTO tblTEST VALUES('Wert2');"
Workspaces(0).Rollback
Workspaces(0).CommitTrans
mDB.Close
Case 1 'oracle
Set mDB = OpenDatabase("", False, dbDriverCompleteRequired,
"ODBC;DSN=VFM70_Ora_ODBC;DBQ=test;DBA=W;PWD=oracle;UID=VFM70;LOGINTIMEOUT=30
")
mDB.Execute "SET TRANSACTION READ WRITE", dbSQLPassThrough
mDB.Execute "INSERT INTO tblTEST VALUES('Wert1')", dbSQLPassThrough
mDB.Execute "SAVEPOINT sp1", dbSQLPassThrough
mDB.Execute "INSERT INTO tblTEST VALUES('Wert2')", dbSQLPassThrough
mDB.Execute "ROLLBACK TO sp1", dbSQLPassThrough
mDB.Execute "COMMIT", dbSQLPassThrough
mDB.Close
End Select
End Sub
> Noch eine Nachfrage habe ich: Wie bestätige ich denn dann bis zu einem
> Savepoint? Geht das überhaupt? Denn in Access geht es wohl, eine innere
> Transaktion einzeln mit Commit zu bestätigen, in der Orahilfe habe ich
aber
> in der Syntax für COMMIT kein "TO savepointxyz" gefunden.
>
Katharina, du musst dir grundlegende Gedanken über den
Transaktionsmechanismuss machen. :-)
Der Transaktionsmechanismuss ist sehr eng mit der Transaktion verküpft,
daher auch die sinnige Bezeichnung.
Verschiedentliche Transaktionen (Insert, Update, Delete) können die
Datenintegrität einer Datenbank erheblich beeinträchtigen.
Daher ist es sinnvoll über die Methoden des Transaktionsmechanismusses sehr
intensiv nachzudenken, denn du kannst auch, durch setzen von falschen
"Savepoints", das Gegenteil von dem Erreichen was du eigentlich bezweckt
hast. Ich kann nur DRINGEND davor warnen solche Mechanismen nicht gezielt
einzusetzen.
(Rufe mich in diesem Zusammenhang an, da kann ich es dir etwas besser
Erklären. Meine Rufnr. schicke ich dir per e-mail)
> jetzt hab ich mal ein kleines Testprogramm gebaut, unter Access geht's
auch
> wunderbar, am Ende und auch erst nach dem CommitTrans ist 'Wert1' zu
sehen.
Hier solltest du aufpassen, denn du machst hier kein gezieltes "Rollback"
(siehe weiter unten)
> Eigentlich müsste das doch im Ora-Teil auch so sein? Ich sehe aber beide
> Werte sofort nach jedem INSERT im SQL Worksheet. Und bei "ROLLBACK TO sp1"
> kommt der Fehler "ORA-01086: Savepoint 'SP1' wurde nicht festgelegt".
Das wundert mich nicht. (siehe weiter unten)
> Dasselbe Ergebnis auch, wenn ich vorher Workspaces(0).BeginTrans absetze.
> Dasselbe Ergebnis auch mit dem Oracle ODBC-Testtool. Irgendwie stehe ich
> anscheinend auf der Leitung :o(
> Katharina
und das wundert mich auch nicht. :-) (soll keine Diskriminierung sein)
> Select Case Index
> Case 0 'access
> Set mDB = OpenDatabase("C:\VB6\Entwicklung\vFM70\Daten\Freiburg.mdb")
> Workspaces(0).BeginTrans
> mDB.Execute "INSERT INTO tblTEST VALUES('Wert1');"
> Workspaces(0).BeginTrans
> mDB.Execute "INSERT INTO tblTEST VALUES('Wert2');"
> Workspaces(0).Rollback
> Workspaces(0).CommitTrans
> mDB.Close
> Case 1 'oracle
> Set mDB = OpenDatabase("", False, dbDriverCompleteRequired,
Also mit DAO kenne ich mich nicht mehr bestens aus aber,
Das was hier geschieht deutet darauf hin, dass DAO jede Transaktion
(BeginTrans) quasi in eine Warteschleife
aufnimmt und du durch Rollback von innen nach aussen jede Transaktion
zerstören kannst.
Dafür spricht, dass das am Ende durchgeführte "CommitTrans" die Transaktion
aus der 1. Transaktion(BeginTrans) festschreibt.
Du kannst aber nicht nach der 2.Transaktion die 1.Transaktion erreichen ohne
die 2. Transaktion gleich mit zu zerstören. Aähnlich dem
Transaktionsmechanismuss von Oracle nur, dass du dort direkt einen Savepoint
anspringen kannst.
"ODBC;DSN=VFM70_Ora_ODBC;DBQ=test;DBA=W;PWD=oracle;UID=VFM70;LOGINTIMEOUT=30
> ")
> mDB.Execute "SET TRANSACTION READ WRITE", dbSQLPassThrough
dies ist unötig (sollte eigentlich "DEFAULT" sein).
Du mußt auf deinem mDB-Objekt BeginTrans ausführen: mDB.BeginTrans
aus diesem Grund bekommst du auch die Fehlermeldung: savepoint ....
> mDB.Execute "INSERT INTO tblTEST VALUES('Wert1')", dbSQLPassThrough
> mDB.Execute "SAVEPOINT sp1", dbSQLPassThrough
> mDB.Execute "INSERT INTO tblTEST VALUES('Wert2')", dbSQLPassThrough
> mDB.Execute "ROLLBACK TO sp1", dbSQLPassThrough
> mDB.Execute "COMMIT", dbSQLPassThrough
> mDB.Close
> End Select
ansonsten müsste das dann gehen :-)
Gruß Carl
ICH HAB'S!
Das Problem war wirklich auf der DAO-Seite, wie du vermutet hast.
Und zwar bleibt auch bei der Oracle-Version unseres Programmes die
DBEngine.DefaultType-Property auf dbUseJet, obwohl keine eingebundenen
Tabellen mehr benutzt werden, und die SQL-Statements werden per PassThrough
weitergeleitet. Hängt wie gesagt mit der Entwicklungsgeschichte zusammen und
weil auch noch eine mdb benutzt wird, die im selben Workspace liegt wie die
Ora-Tabellen.
Wenn ich im Testprogramm umstelle auf dbUseODBC, geht's wunderbar - Code am
Ende.
Das Problem ist also, dass die von DAO angesprochene Jet-Engine Oracle nicht
weitermeldet, dass ein BeginTrans ausgeführt wurde, es über ODBCDirect aber
offensichtlich funktioniert.
Vielen Dank noch mal für deine Hilfe!!!
Katharina
Option Explicit
DefInt A-Z
Option Compare Text
Dim mWS As Workspace
Dim mDB As Database
Private Sub cmdCommand_Click(Index As Integer)
Select Case Index
Case 0 'access
Set mDB = OpenDatabase("C:\VB6\Entwicklung\vFM70\Daten\Freiburg.mdb")
Workspaces(0).BeginTrans
mDB.Execute "INSERT INTO tblTEST VALUES('Wert1');"
Workspaces(0).BeginTrans
mDB.Execute "INSERT INTO tblTEST VALUES('Wert2');"
Workspaces(0).Rollback
Workspaces(0).CommitTrans
mDB.Close
Case 1 'oracle
DBEngine.DefaultType = dbUseODBC
Set mWS = CreateWorkspace("mWS", "Admin", "")
DBEngine.Workspaces.Append mWS
Set mDB = DBEngine.Workspaces(1).OpenDatabase("", False,
dbDriverCompleteRequired,
"ODBC;DSN=VFM70_Ora_ODBC;DBQ=test;DBA=W;PWD=oracle;UID=VFM70;LOGINTIMEOUT=30
")
Workspaces(1).BeginTrans
mDB.Execute "INSERT INTO tblTEST VALUES('Wert1')"
mDB.Execute "SAVEPOINT sp1"
mDB.Execute "INSERT INTO tblTEST VALUES('Wert2')"
mDB.Execute "ROLLBACK TO sp1"
mDB.Execute "COMMIT"
Workspaces(1).CommitTrans