Laden...

Oracle SQL Abfrage abbrechen

Erstellt von Net_Hans vor 13 Jahren Letzter Beitrag vor 13 Jahren 7.265 Views
N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren
Oracle SQL Abfrage abbrechen

Hallo,

ich habe vor einen Datenbankabfrage durchzuführen, welche mehrere Minuten dauern kann. Da dieses in einem Windowsservice laufen soll, muss ich unter bestimmten Bedingungen (stoppen vom Service etc.) das Programm schnellst möglich stoppen können. Wie kann ich im folgendem Coldeauszug den Abbruch erkennen und die SQL Abfrage abzubrechen.?

using (OracleConnection connection = new OracleConnection())
                {
                    connection.ConnectionString = connectionString;
                    connection.Open();
                    OracleCommand command = connection.CreateCommand();
                    OracleDataReader reader;
                    string sql;
                    sql = "SELECT * FROM TESTVIEW ";


                    command.CommandText = sql;
                    reader = command.ExecuteReader();
                    ...

Das Abbrechen wird in Form von einer Variable vorliegen ... sprich wenn zB. die Variable sys_cancel auf true gesetzt wird soll die SQL Abfrage stoppen.

Gibt es da eine Lösung?

Danke für eure Hilfe
mfG Hans

C
101 Beiträge seit 2008
vor 13 Jahren

Ich würd dir vorschlagen das ganze mit einer Transaction zu machen


using (OracleConnection myConnection = new OracleConnection())
                {
                    myConnection = AGB70.PABS.Common.Var.gblDBInfo.GetDbConnection();
            myConnection.Open();

            //Definiert den Start einer Übertragung
            myTransaction = myConnection.BeginTransaction(); //vielleicht noch isolationslevel hinzufügen

            //Erstellt ein Commandobjekt, welches die SQL-Statements ausführt
            myCommand = AGB70.PABS.Common.Var.gblDBInfo.GetDbCommand();
            mytCommand.Connection = myConnection;
            mytCommand.Transaction = myTransaction;
}

so kannst du schlussendlich mit rollback alles rückgängig machen


if (sys_cancel)
{
 myTranscation.Rollback();
}

ps. am schluss nicht den commit vergessen

1.818 Beiträge seit 2005
vor 13 Jahren

Hallo!

Man könnte auch alles in einen separaten Thread packen, und diesen dann bei bedarf beenden. Dadurch wird auch die Abfrage beendet.

Nobody is perfect. I'm sad, i'm not nobody 🙁

N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

Hallo,

danke schon mal für die ersten vorschläge.

@chanderegg
Das mit der Transaktion habe ich glaube nicht 100% verstanden. Da ich nur Abfragen (SELECT) verarbeite, werde ich kein Rollback benötigen.

Mein Problem ist viel mehr das das die Abfrage alleine schon mehrere Minuten benötigt.

@tom-essen
Die Idee mit dem separaten Theader hatte ich auch schon, aber die Idee wollte ich nicht weiter verfolgen, da das ja bedeuten würde, das ich die Oracle Verbindung "abschieße" und ich so eventuell Fehler und Deadlocks erzeuge könnte.

Kann man so einen hartes abschießen nicht irgendwie verhindern?

Bei meinem Datenbank Tool (Toad) kann man die SELECT Anweisungen auch schön sauber abbrechen.

mfG Hans

W
955 Beiträge seit 2010
vor 13 Jahren

Hallo,

Du könntest Deine sid (session instance identifier) und die serial# vor der lang laufenden Anfrage auslesen (v$session?) und mit ALTER SYSTEM KILL SESSION in einem anderen Thread beenden,.

http://www.wer-weiss-was.de/theme165/article1867698.html

N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

Hallo witte,

wenn ich mir das richtig durchgelesen habe, müsste ich um sicher zu stellen, das die Session gekillt wird wirklich hart killen mit diesem -9. ... hmm so toll finde ich das aber auch nicht, meinem Programm einfach die Oracle Session weg zu nehmen.

Es muss doch möglich sein, die Transaktion sauber zu beenden (auf einem dafür vorgesehenen Weg) ohne ein kill oder ähnliches.

So nach dem Motto, cancel Transaktion xy ... und Oracle bricht dann kontrolliert die Anfrage ab.

Ich bin ganz ehrlich von diesem "Ach beenden / killen wir es einfach hart ... wird schon nichts passieren" halte ich nicht alt so viel ... Am Ende gibt das nur Probleme.

W
955 Beiträge seit 2010
vor 13 Jahren

Ich bin ganz ehrlich von diesem "Ach beenden / killen wir es einfach hart ... wird schon nichts passieren" halte ich nicht alt so viel ... Am Ende gibt das nur Probleme. Das ist quatsch. Ein Serversystem taugt nichts wenn es durch solche Abbrüche in die knie zwingen läßt. Wäre ja ne prima DOS-Attacke.
Aber Du sollst ja nicht den OS-Prozeß killen sondern die Oracle-Session. Ich glaube nicht dass das auf Transaktionsebene geht. Dein TOAD wird es wahrscheinlich auch so handhaben: die SID aus der ersten Transaktion vorher auslesen und in einer zweiten Verbindung abbrechen. Du kannst ja mal mit einem Profiler/Wireshark den Datentransfer mitschneiden und schauen was bei TOAD passiert.

X
1.177 Beiträge seit 2006
vor 13 Jahren

huhu,

eine Transaktion abzubrechen schadet keinem DB-System. Genau dafür sind Transaktionen da. Auch das beenden einer Verbindung sorgt in dem Fall für einen Rollback der Transaktion. Sogar bei einem Stromausfall wird im Normalfall beim wiederanlaufen der DBs geguckt, ob man noch ein paar transaktionen, welche nicht fertig waren, wieder rückgängig machen muss.

Für dein Problem gibts aber IDbCommand.Cancel(). Dann würde ich aber auch zusätzlich die BeginXXX-Methoden verwenden um das ganze asynchron zu halten.

😃

xynratron

Herr, schmeiss Hirn vom Himmel - Autsch!

Die Erfahrung zeigt immer wieder, dass viele Probleme sich in Luft auslösen, wenn man sich den nötigen Abstand bzw. Schlaf gönnt.

N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

Hallo,

das mit der IDbCommad.Cancel() klingt doch gut, kann mir dazu eventuell mal ein beispiel geben ... denn ich hänge bei dieser Idee an dem Punkt, wo ich der Meinung bin, das mein Programm beim

reader = command.ExecuteReader();

solange wartet, bis dieser Befehl durch gelaufen ist. und somit kann ich ja das Cancel nicht durchführen oder?

F
10.010 Beiträge seit 2004
vor 13 Jahren

Weshalb dir Xynratron auch gleich geraten hat die Asynchronen Beginxxx Funktionen zu nutzen.

N
Net_Hans Themenstarter:in
70 Beiträge seit 2010
vor 13 Jahren

Achso ... den Befehl gibt es wirklich ... ich dachte das mit dem xxx war mehr ein Beispiel ... ist das sowas wie der Backgroundworker?