Seiten

Freitag, 31. Mai 2013

DB-Version und -Patchstand erfragen

Wenn man die Oracle-DB gepatcht hat - oder noch patchen möchte - möchte man vorher oder nachher sicher gern wissen, wie es in der DB versionsmäßig aussieht. Dafür reicht die v$version-View nicht - was man vielleicht erwarten würde.
--Versionsstand der Installation(en)
select * from v$version;

--oder für RAC
SELECT * FROM GV$VERSION;
Will man den Patchstand der DB erfahren, muss man in die DBA_REGISTRY sehen
--Patchstand der DB
SELECT * FROM DBA_REGISTRY_HISTORY
Weitere Views, die irgendwie REGISTRY-Bezug haben, findet man im Datadictionary.
SELECT * FROM DICTIONARY
WHERE TABLE_NAME LIKE 'DBA_REGISTRY%'
Interessant sind vielleicht diese 2:
--auf welcher Plattform läuft die DB?
SELECT * FROM DBA_REGISTRY_DATABASE

--geladene Komponenten
SELECT * FROM DBA_REGISTRY

Montag, 6. Mai 2013

APEX mobil - Zugriff auf's Smartphone-GPS

Mit Apex 4.2 ist es sehr einfach, Webseiten für mobile devices zu erstellen.
Sogar der Zugriff auf einige Smartphone-Funktionen ist über den Browser möglich.
Ich habe beispielhaft den Zugriff auf den Standort implementiert:
  • Auf einer Webseite soll die Position des Smartphones dargestellt werden.
  • Über den Klick eines Buttons wird der Browser die API ansprechen und Höhe und Breite abrufen.
  • Höhe und Breite werden zusätzlich angezeigt, damit man auch Änderungen registrieren kann.
Zunächst habe ich mir auf http://apex.oracle.com einen kostenlosen Workspace angelegt und anschließend schnell mal eine Anwendung mit dem Mobile-Template zusammengeklickt. Wie man das macht, ist in diesem Tipp der deutschsprachigen APEX und PL/SQL Community beschrieben.
Hier im Schnelldurchlauf:
  • Den Wizard für eine neue Applikation aufrufen und eine Datenbankapplikation auswählen.
  • Name, Schema, Optionen, Template auswählen
Die obligatorischen Angaben machen und weiter
  • Im Wizard bis zum Schluss immer nur auf "Weiter" klicken und Anwendung erstellen. Ob man - wie ich hier - ohne Login arbeiten möchte ist natürlich Geschmackssache.
Das Ergebnis
  • Jetzt vergeben wir noch schnell einen Aliasnamen, damit man sich nicht die Anwendungs-ID merken muss.
Damit steht das Grundgerüst und kann mit dieser URL aufgerufen werden: http://apex.oracle.com/pls/apex/f?p=gpstest
Auf der Home-Seite wird ein Button platziert, der bei einem Klick eine Dynamic Action auslöst. Hinter dieser liegt etwas JavaScript, welches das GPS-Modul des Smartphones abfragt.
Den Button bekommt man, indem man nacheinander:
  1. eine Region erstellt und dann dort
  2. den Button erstellt
Rechtsklick auf "Regionen"
In der Region muss noch HTML eingetragen werden, welches später per JavaScript manipuliert wird:
Wer schon mal mit JavaScript Webseiten manipuliert hat, der weiß, dass die ID eines Elementes für den gezielten Zugriff auf selbiges benötigt wird.
Jetzt per Rechtsklick auf die neue Region den Wizard für die Buttonerstellung starten.
Dem neuen Button verpassen wir - ebenfalls per Rechtsklick - eine "dynamic action"
Benamsen und weiter
weiter
Mussfelder sinnvoll füllen und weiter

Den JavaScript-Code einfügen, weiter zum letzten Schritt und dann fertigstellen.

Das Javascript findet man bequem per Google mit diesen Suchbegriffen: jquery mobile geolocation und kann ihn dann modifizieren.
navigator.geolocation.getCurrentPosition (function (pos)
{
  var lat = pos.coords.latitude;
  var lng = pos.coords.longitude;
  var t = new Date();
  var Monat = new Array("01", "02", "03", "04", "05", "06",
                        "07", "08", "09", "10", "11", "12")
  var Tag = t.toGMTString();
  var Tag = t.getDate() + "." + Monat[t.getMonth()] + "." + t.getFullYear()        + " "  + t.getHours() + ":" + t.getMinutes() + ":" +
          + t.getSeconds();
  var Tag = t.toLocaleString() ;
  var ts = t.getTime();
  $("#time").text (Tag);
  $("#ts").text (ts);
  $("#lat").text (lat);
  $("#lng").text (lng);
});

Hier kann man sich das unspektakuläre Ergebnis mit dem Iphone/Androiden/Blackberry/WindowsPhone ansehen: http://apex.oracle.com/pls/apex/f?p=gpstest
Eine Fehlerbehandlung habe ich mir gespart. Deshalb wird auch nichts passieren, sofern man gerade keinen freien Himmel hat.
Dieses Beispiel ließe sich jetzt bequem erweitern:
  • wegschreiben des Standpunktes in die DB (GPS-Tracking)
  • Darstellung des Standortes auf einem Kartendienst
  • ...

Fazit:

Mit APEX ist eine mobile Webseite extrem schnell "zusammengeklickt". Natürlich muss man für komplexe Anwendungen unter APEX mehr Aufwand investieren, dafür muss man sich nicht mit lästigen Arbeiten rund um Login, Datenbankzugriff, Browserkompatibilitäten... herumschlagen.
Schneller als mit APEX kommt man wohl nicht zu einer mobile-app-ähnlichen Webseite für Smartphones - erst recht nicht, wenn man sich darauf beschränkt, Datenbankinhalte auf dem Smartphone "nur" darzustellen.
Auch wenn man mehr machen möchte, kommt man sehr schnell zu einem guten Ergebnis.

Derzeit ist geolocation aber die einzige interessantere herstellerübergreifende Gerätefunktion, auf die der Smartphone-Browser zugreifen kann. Richtig interessant wird es erst, wenn der Browser Zugriff auf z.B. die Kamera bekommt. Dann ließen sich tolle Anwendungen in APEX erstellen, die bisher den nativen Apps vorbehalten sind.
Auf http://mobilehtml5.org/ werden die Fähigkeiten der gängigen Smartphone-OS aufgelistet. Bisher können nur Blackberry (Z10), sowie Android & Symbian (Opera Mobile) mit der Unterstützung von getUserMedia aufwarten - also dem Zugriff auf die Kamera.

Donnerstag, 25. April 2013

Bug im jQuery Mobile von APEX 4.2.1: "Error loading page"

Das jQuery Mobile, welches mit APEX 4.2.1 ausgeliefert wird, hat einen gemeinen Bug (bug# 16184694), der zuschlägt, sobald man nicht direkt auf den Webserver/APEXListener zugreift, sondern der Zugriff per redirect durch einen Proxy geleitet wird - das ist z.B. dann der Fall, wenn per Smartphone auf die DB zugegriffen werden soll und der Webserver in der DMZ steht.
Bei mir verhinderte der Bug bereits das Login in die Applikation.

Lösung:
Enter

$("#wwvFlowForm", apex.gPageContext$).attr("data-ajax", false);

into "Execute when Page Loads" attribute of page which contains the select list page item to not use an AJAX call for the submit. Avoiding the AJAX call will trigger a full page refresh which will also cleanup the jQuery Mobile call stack.
Quelle: https://forums.oracle.com/forums/thread.jspa?messageID=10857686&tstart=0

Freitag, 19. April 2013

Systemstatistiken

In der 01/2013 der DOAG News ist ein sehr empfehlenswerter Artikel von Thorsten W. Grebe über die Oracle Systemstatistiken zu finden: “Glücksspiel Systemstatistiken - Das Märchen vom typischen Workload“ (S.52) Auf  www.twg-it.de ist dazu sein Vortrag auf der DOAG-Konferenz zu finden.
Hr. Grebe stellt in dem DOAG-News-Artikel sehr gut dar, dass es nicht so einfach ist, an verlässliche Systemstatistiken zu kommen, wie Oracle es in seiner Doku unterstellt.
Hier sieht man die Defaultwerte einer unberührten DB:

SQL> set wrap off;
SQL> col sname format a20;
SQL> col pname format a20;
SQL> col pval2 format a20;
SQL> select * from aux_stats$;

SNAME                PNAME                     PVAL1 PVAL2
-------------------- -------------------- ---------- --------------------
SYSSTATS_INFO        STATUS                          COMPLETED
SYSSTATS_INFO        DSTART                          11-03-2011 06:38
SYSSTATS_INFO        DSTOP                           11-03-2011 06:38
SYSSTATS_INFO        FLAGS                         1
SYSSTATS_MAIN        CPUSPEEDNW           1720,20725
SYSSTATS_MAIN        IOSEEKTIM                    10
SYSSTATS_MAIN        IOTFRSPEED                 4096
SYSSTATS_MAIN        SREADTIM
SYSSTATS_MAIN        MREADTIM
SYSSTATS_MAIN        CPUSPEED
SYSSTATS_MAIN        MBRC
SYSSTATS_MAIN        MAXTHR
SYSSTATS_MAIN        SLAVETHR

13 Zeilen ausgewählt.

Abgelaufen: 00:00:00.01
SQL>
Die No-Workloadwerte sind IOSEEKTIM und IOTFRSPEED.

Die Workloadstatistiken waren mir schon lange suspekt. Weil ich mir bisher nie sicher war, wann und wie lang ich die Workloadstatistiken aufzeichnen soll, habe ich es lieber ganz sein lassen. Und das ist bis auf weiteres auch in Ordnung. Für gute Workloadstatistiken muss mehr Aufwand betrieben werden, als Oracle Glauben machen will.
Und hier gilt diesmal im Gegensatz zu den Objektstatistiken: Lieber Defaultstatistiken als schlechte Statistiken.

Wobei: Für die No-Workloadstatistiken gilt das nicht ganz, bzw. ist hier zumindest der Aufwand nicht so hoch, wie für die Generierung plausibler Workloadstatistiken.
Die No-Workload-Statistiken kann man ruhig generieren, wenn man auch tatsächlich prüft, ob die Werte sinnvoll sind. Wird der DB-Server gerade stark beansprucht, während die No-Workloadwerte generiert werden, können auch diese Statistiken verfälscht werden.

No-Workloadstatistiken generiert man mit dem Package DBMS_STATS:
SQL> exec DBMS_STATS.GATHER_SYSTEM_STATS();

PL/SQL-Prozedur erfolgreich abgeschlossen.

Abgelaufen: 00:00:08.95
SQL> select * from aux_stats$;

SNAME                PNAME                     PVAL1 PVAL2
-------------------- -------------------- ---------- --------------------
SYSSTATS_INFO        STATUS                          COMPLETED
SYSSTATS_INFO        DSTART                          04-19-2013 07:32
SYSSTATS_INFO        DSTOP                           04-19-2013 07:32
SYSSTATS_INFO        FLAGS                         1
SYSSTATS_MAIN        CPUSPEEDNW                 1460
SYSSTATS_MAIN        IOSEEKTIM                     7
SYSSTATS_MAIN        IOTFRSPEED                28796
SYSSTATS_MAIN        SREADTIM
SYSSTATS_MAIN        MREADTIM
SYSSTATS_MAIN        CPUSPEED
SYSSTATS_MAIN        MBRC
SYSSTATS_MAIN        MAXTHR
SYSSTATS_MAIN        SLAVETHR

13 Zeilen ausgewählt.

Abgelaufen: 00:00:00.00
SQL>

Workloadstatistiken lassen sich natürlich auch manuell einstellen (dbms_stats.set_systems_stats(...)) oder auf Default zurücksetzen (dbms_stats.delete_system_stats()):
SQL> exec DBMS_STATS.DELETE_SYSTEM_STATS ();

PL/SQL-Prozedur erfolgreich abgeschlossen.

Abgelaufen: 00:00:00.01
SQL> select * from aux_stats$;

SNAME                PNAME                     PVAL1 PVAL2
-------------------- -------------------- ---------- --------------------
SYSSTATS_INFO        STATUS                          COMPLETED
SYSSTATS_INFO        DSTART                          04-19-2013 07:38
SYSSTATS_INFO        DSTOP                           04-19-2013 07:38
SYSSTATS_INFO        FLAGS                         0
SYSSTATS_MAIN        CPUSPEEDNW                 1460
SYSSTATS_MAIN        IOSEEKTIM                    10
SYSSTATS_MAIN        IOTFRSPEED                 4096
SYSSTATS_MAIN        SREADTIM
SYSSTATS_MAIN        MREADTIM
SYSSTATS_MAIN        CPUSPEED
SYSSTATS_MAIN        MBRC
SYSSTATS_MAIN        MAXTHR
SYSSTATS_MAIN        SLAVETHR

13 Zeilen ausgewählt.

Abgelaufen: 00:00:00.00
SQL>

Beruhigend: Erst wenn man tatsächlich Performanceprobleme und die Systemstatistiken als Ursache identifiziert hat, muss man sich eingehend mit dem Thema befassen.
Bis dahin gilt weiter: Ursache Nr.1 für Performanceprobleme in der Anwendung ist schlechtes SQL.

Mittwoch, 13. März 2013

Tabellenimport auf die Schnelle mit APEX

APEX bietet mit seinen Websheets eine einfache Möglichkeit gemeinsam in einem Team/ einem Projekt Daten im Browser zu bearbeiten. Wie einfach das funktioniert, kann man sich in diesem Youtube-Video der MT AG ansehen.

Das ist schon mal ganz nett, aber man möchte die gleichen Daten vielleicht viel lieber in einer APEX-Applikation verarbeiten und benötigt sie direkt in einer Tabelle.
Mit APEX geht das sehr schnell und sehr leicht.
Wie das geht, ist hier ausführlich beschrieben.
Unter "SQL Workshop">"Data Workshop" findet man den Startpunkt für Export/Import.
Hier wird man von Wizards an die Hand genommen und Schritt für Schritt zum Ziel geführt.

Man kann Daten sowohl in eine vorhandene Tabelle importieren, als auch eine komplett neue Tabelle über den Import generieren. Letzteres ist sehr nützlich, wenn man "mal schnell" Tabellen und Daten für einen Prototypen benötigt und sich nicht ausführlich mit dem Entwurf eines Datenmodells befassen möchte.
Als Datenquelle können CSV- und XML-Files dienen. Per copy&paste kann man die Daten ebenfalls nach APEX bringen.

Mittwoch, 27. Februar 2013

APEX - About Choosing a Web Listener

Laut Doku kann APEX über 3 Möglichkeiten mit dem Browser sprechen:
  1. Oracle Application Express Listener
  2. Embedded PL/SQL Gateway
  3. Oracle HTTP Server (OHS)
Wenn man den OHS (ist ein Apache) nutzen möchte, darf man der Doku nicht glauben. Tut man das doch und nimmt den Punkt Step 5: Configure Oracle HTTP Server Distributed with Oracle Database 11g or Oracle Application Server 10g für bare Münze, so sucht man vergeblich in der DB-Installation nach dem OHS.
Im OTN bin ich dann fündig geworden: Der OHS ist nicht mehr Teil der Datenbankinstallation und muss jetzt separat heruntergeladen und installiert werden. (hier)
Jetzt stellt sich natürlich wieder die Frage der Lizensierung des OHS. Wahrscheinlich ist die Nutzung über die Datenbank lizensiert und auf den Server beschränkt. Besser man fragt Oracle direkt.
Einstweilen nutze ich weiter den APEX Listener.

Freitag, 15. Februar 2013

Flashback mit der Standard Edition

Flashback ist eine coole Sache. Wenn man auf einer Enterprise Edition (EE) arbeiten kann, schöpft man natürlich aus dem Vollen:
  • Flashback Query, Flashback expdp/exp
  • Flashback Version Query
  • Flashback Drop
  • Flashback Transaction Query (wirklich nur EE?)
  • Flashback Table (nur EE)
  • Flashback Database (nur EE)
  • Flashback Transaction (nur EE)
  • Total Recall: Flashback Data Archive (ab 11g, natürlich nur EE und das auch nur als Option)
In der Standard Edition (SE) kann man leider nur die ersten 3 Features nutzen. Aber bereits diese können sehr wertvoll sein und sind in vielen Fällen völlig ausreichend.
Wie also nutzt man Flashback in der SE?
Bevor man überhaupt daran denken kann, Flashback zu nutzen, sollte man sicher gehen, dass das dafür Nötige konfiguriert ist.
Die Parameter UNDO RETENTION und RECYCLEBIN müssen entsprechend gesetzt sein und der UNDO-Tablespace muss über ausreichend Platz verfügen.
Will man Flashback Transaction Query nutzen, muss außerdem Supplemental Logging eingeschaltet sein. Aber dazu unten mehr.

UNDO RETENTION

SQL> show parameter undo_retention

NAME                                 TYPE        VALUE
------------------------------------ ----------- ------
undo_retention                       integer     900
900 ist der Standardwert in Sekunden. Diese 15min sind kein wirklich beruhigendes Zeitpolster. Wir setzen den Wert also etwas etwas höher - z.B. auf 7200 (2 Stunden).
SQL> ALTER SYSTEM SET UNDO_RETENTION=7200;
Problem: Der UNDO_RETENTION-Wert ist nur das Ziel der DB und wird nicht garantiert. Es ist möglich bzw. in einer produktiven DB wahrscheinlich, dass durch DML zu viel UNDO benötigt wird und damit das tatsächlich nutzbare Zeitpolster schrumpft. In diesem Fall bekommt ein FLASHBACK QUERY möglicherweise einen "ORA-01555 snapshot too old...".
Wenn man das verhindern möchte, kann man zusätzlich die RETENTION GUARANTEE auf dem UNDO-Tablespace setzen.
Das wiederum zieht dann möglicherweise ein Folgeproblem nach sich:
Ist der UNDO aufgebraucht und weitere DML-Operationen laufen auf, werden diese Operationen mangels UNDO fehlschlagen.
Dagegen hilft dann natürlich nur ein ausreichend großer UNDO-Tablespace.
Wir sehen nach, ob die Garantie konfiguriert ist:
SQL> SELECT TABLESPACE_NAME, RETENTION FROM DBA_TABLESPACES WHERE CONTENTS = 'UNDO';

TABLESPACE_NAME                RETENTION
------------------------------ -----------
UNDOTBS1                       NOGUARANTEE
Und so verschafft man sich diese Garantie:
SQL> ALTER TABLESPACE UNDOTBS1 RETENTION GUARANTEE;

PAPIERKORB

Den Papierkorb/Recyclebin benötigt man für die Wiederherstellung versehentlich gelöschter Tabellen.
Ist der Papierkorb an?
SQL> show parameter recyclebin;

NAME                                 TYPE        VALUE
------------------------------------ ----------- -----
recyclebin                           string      on
Wenn nicht, dann:
SQL> ALTER SYSTEM SET RECYCLEBIN='ON'

Flashback Query

Jemand setzt ein DELETE oder UPDATE mit der der falschen oder gar keiner WHERE-Bedingung ab und schon herrscht Panik. Sofort wird ein DB-Recovery verlangt.
Ein incomplete recovery ist natürlich selten eine gute Lösung für dieses Problem.
Sofern der faux pas nicht zu weit zurückliegt (UNDO RETENTION!), lassen sich die korrekten Daten per FLASHBACK QUERY wieder hervorzaubern.
Da die Uhr tickt und der Ablauf UNDO RETENTION wie ein Damokleschwert über dem unglücklichen User schwebt, sichert man am besten den Datenbestand per CTAS in eine Tabelle.
SQL> CREATE TABLE jobs_rettung AS (SELECT * FROM jobs AS OF TIMESTAMP to_timestamp('10.02.2013 13:00','dd.mm.yyyy hh24:mi:ss'));
Von hier aus kann man die Daten in Ruhe wieder reparieren.
Eine andere Methode, den vergangenen Augenblick zu sichern bieten expdp und das alte exp.
Mit dem Parameter FLASHBACK_TIME/FLASHBACK_SCN weist man expdp/exp an, die Vergangenheit in ein dump-file zu pressen.
expdp system/@orcl dumpfile=jobs_flashback.dmp logfile=jobs_flashback_exp.log directory=expdp schemas=hr flashback_time='2013-02-10-13:00:00'
ODER:
expdp system/@orcl dumpfile=jobs_flashback.dmp logfile=jobs_flashback_exp.log directory=expdp schemas=hr flashback_scn='3416833'

Flashback Versions Query

Der User, der das verhängnisvolle DELETE/UPDATE abgesetzt hat, weiß unter Umständen gar nicht, wann genau das war. Er weiß vielleicht auch nur die ungefähre Zeit. Das ist uns alles zu ungenau. Wir hätten gern den genauen Zeitpunkt - besser noch die SCN. Um das zu erfahren, hat Oracle Flashback Versions Query und ein paar nützliche Pseudospalten spendiert.
Wenn man den genauen Zeitpunkt erfahren möchte, zu dem Werte geändert wurden, stürzt man sich auf die Spalten VERSIONS_STARTSCN und VERSIONS_STARTTIME der FLASHBACK VERSIONS QUERY.
Wir ändern als Beispiel einfach mal das Gehalt in der Tabelle jobs:
SQL> update jobs set min_salary=7777 where job_title='Accountant';

1 Zeile wurde aktualisiert.

Abgelaufen: 00:00:00.00
SQL> commit;

Transaktion mit COMMIT abgeschlossen.

Abgelaufen: 00:00:00.00
SQL> update jobs set max_salary=11111 where job_title='Accountant';

1 Zeile wurde aktualisiert.

Abgelaufen: 00:00:00.01
SQL> commit;

Transaktion mit COMMIT abgeschlossen.

Abgelaufen: 00:00:00.00
Und jetzt sehen wir uns den Änderungsverlauf an:
SQL> COL VERSIONS_XID FORMAT A17
SQL> COL VERSIONS_STARTTIME FORMAT A18
SQL> COL JOB_TITLE FORMAT A10
SQL> SELECT VERSIONS_XID, VERSIONS_OPERATION,
  2  VERSIONS_STARTSCN , VERSIONS_STARTTIME,
  3  --VERSIONS_ENDSCN, VERSIONS_ENDTIME,
  4  JOB_TITLE, MIN_SALARY, MAX_SALARY
  5  FROM JOBS VERSIONS BETWEEN SCN MINVALUE AND MAXVALUE
  6  WHERE JOB_TITLE='Accountant'
  7  ORDER BY VERSIONS_STARTSCN;

VERSIONS_XID      V VERSIONS_STARTSCN VERSIONS_STARTTIME JOB_TITLE  MIN_SALARY MAX_SALARY
----------------- - ----------------- ------------------ ---------- ---------- ----------
02002100270B0000  U           3538077 10.02.13 13:00:46  Accountant       7777       9000
010020007D0A0000  U           3538081 10.02.13 13:00:48  Accountant       7777      11111
                                                         Accountant       4200       9000

3 Zeilen ausgewählt.
Die letzte Zeile hat keine Werte in den Spalten VERSIONS_XID, V, VERSIONS_STARTSCN und VERSIONS_STARTTIME. Das ist der Ursprungszustand. In Spalte V wird über die Kürzel I(nsert), U(pdate) und D(elete) die Änderungsoperation angegeben. Mit diesen Angaben kann man dann FLASHBACK QUERY wie oben nutzen, um die alten Werte zu ziehen und weiter zu verarbeiten.

Flashback Drop

Per FLASHBACK DROP kann ein DROP TABLE rückgängig gemacht werden. Dabei wird sowohl die Tabelle, als auch deren Indizes, Constraints usw. gerettet.
Eine gelöschte Tabelle kann solange wieder hergestellt werden, wie der von ihr genutzte Platz im Tablespace nicht benötigt wird. Die UNDO RETENTION spielt hier ausnahmsweise keine Rolle.
Dieses Flashback-Feature ist meiner Meinung nach das langweiligste. Das liegt aber vielleicht daran, dass ich noch nie aus Versehen eine Tabelle gelöscht habe. :)
SQL> DROP TABLE jobs;

Tabelle wurde gelöscht.

Abgelaufen: 00:00:00.18
SQL> SELECT object_name, original_name, type, droptime
  2       FROM user_recyclebin;

OBJECT_NAME                    ORIGINAL_NAME                    TYPE
DROPTIME
------------------------------ -------------------------------- ---------
BIN$/KCe7FP4T/6HZfUeTGb53A==$0 JOBS                             TABLE
2013-02-10:13:00:46
SYS_LOB0000830301C00003$$      SYS_LOB0000830301C00003$$        LOB
2013-02-10:12:37:46
SYS_IL0000830301C00003$$       SYS_IL0000830301C00003$$         LOB INDEX
2013-02-10:12:37:46

3 Zeilen ausgewählt.

Abgelaufen: 00:00:00.02

SQL> FLASHBACK TABLE "BIN$/KCe7FP4T/6HZfUeTGb53A==$0" TO BEFORE DROP RENAME TO jobs;

Flashback abgeschlossen.

Abgelaufen: 00:00:00.04

Flashback Transaction Query

Eigentlich ist hier Schluss mit den SE-Flashback-Features, denn Flashback Transaction Query ist laut Oracle ein EE-Feature.
Aber beim Testen ist mir aufgefallen, dass man auch in der SE die Möglichkeit besitzt, Flashback Transaction Query zu nutzen.
Einzige Voraussetzung: Man muss SUPPLEMENTAL LOGGING aktivieren.
Ich bin davon ausgegangen, dass das in der SE gar nicht funktioniert, aber naja...
Also: Ist das Logging eingeschaltet?
SQL> select SUPPLEMENTAL_LOG_DATA_MIN from v$database;

SUPPLEME
--------
NO

1 Zeile wurde ausgewõhlt.
Supplemental Logging ist standardmäßig abgeschaltet. Und so schaltet man es ein:
SQL> alter database add supplemental log data;
Dieses Logging schreibt zusätzliche Informationen in die DB. Per Flashback Transaction Query kann man sich damit DML ausgeben lassen, welche die geloggten Operationen rückgängig machen. Aus einem DELETE wird ein INSERT und umgekehrt, ein UPDATE-Befehl findet seine entsprechende Korrektur usw.
Logging bedeutet auch zusätzliche Last auf der DB. Das muss man sich natürlich vor Augen führen, bevor man die Entscheidung zur Aktivierung trifft.
Und so holt man sich das UNDO_SQL:
SQL> conn / as sysdba
Connect durchgeführt.
Abgelaufen: 00:00:00.00

GLOBAL_NAME
--------------------------------------------------
sys@ORCL 10.02.2013 13:30:34
Abgelaufen: 00:00:00.00

SQL> SELECT UNDO_SQL FROM FLASHBACK_TRANSACTION_QUERY WHERE XID = '02002100270B0000';

UNDO_SQL
--------------------------------------------------------------------------------
update "HR"."JOBS" set "MIN_SALARY" = '4200' where ROWID = 'AAASbGAAFAAAAC/AAE';

2 Zeilen ausgewählt.

Abgelaufen: 00:00:06.83
SQL> update "HR"."JOBS" set "MIN_SALARY" = '4200' where ROWID = 'AAASbGAAFAAAAC/AAE';

1 Zeile wurde aktualisiert.

Abgelaufen: 00:00:00.00
Wie gesagt, handelt es sich hier um ein EE-Feature. In der SE sollte man es keinesfalls nutzen. Wahrscheinlich ist bereits das Einschalten des SUPPLEMENTAL LOGGING lizenzpflichtig.

Fazit

Flashback ist ein tolles Feature der Oracle-DB. Bereits mit den Möglichkeiten, die die SE bietet, kommt man sehr weit:
Es ist recht einfach möglich, den genauen Fehlerzeitpunkt zu bestimmen (Flashback Versions Query) und die Daten lassen sich dann damit einfach aus der Vergangenheit in die Gegenwart holen.