Wollten Sie immer schon mal wissen, welche BIlder in Ihrer Seite vorkommen? Wenn man das über die APEX Tabellen lösen möchte wird es schwierig, denn davon gibt es fast 600.
Wir verwenden deswegen einen anderen Ansatz: Wir rendern die Seite und suchen dann nach Links oder Bildern.
Geben Sie dazu im Kopf des SQL Statements die Werte für die Application ID (hier 100
Bilder in einer Seite finden:
WITH my_app as (select 100 as app_id, 1 as page_id FROM dual) SELECT my_app.app_id,my_app.page_id,replace(column_value,'/','/') img FROM TABLE ( SELECT APEX_STRING.GREP(page, '<img src[^>]*','i')as bilder FROM ( select apex_web_service.make_rest_request( p_url=>'https://www.muniqsoft-training.de/ords/oracle/r/muso_training/schulung/'||page_alias, p_http_method=>'GET', p_wallet_path=>'file:///opt/oracle/admin/FREE/https_wallet' ) as page from apex_application_pages app,my_app where app.application_id=my_app.app_id and app.page_id =my_app.page_id)),my_app /
Links in einer Seite finden:
WITH my_app as (select 100 as app_id, 1 as page_id FROM dual) SELECT my_app.app_id,my_app.page_id,replace(column_value,'/','/') link FROM TABLE ( SELECT APEX_STRING.GREP(page, '<a href=*[^>]*">[[:alnum:] ]{1,}<\/a>' ,'i')as bilder FROM ( select apex_web_service.make_rest_request( p_url=>'https://www.muniqsoft-training.de/ords/oracle/r/muso_training/schulung/'||page_alias, p_http_method=>'GET', p_wallet_path=>'file:///opt/oracle/admin/FREE/https_wallet' ) as page from apex_application_pages app,my_app where app.application_id=my_app.app_id and app.page_id =my_app.page_id)),my_app;
Weitere Tipps erfahren Sie in unserem APEX Kurs
Wie oft habe ich schon nach der Syntax gesucht um nachträglich einen Constraint auf eine Tabelle zu legen. Google ist ja da immer eine gute Hilfe, aber in deutsch gab es bisher wenig.Das ändert sich nun, wir beschätigen uns mit dem Thema Constraints hier nun.Nachträglich einen Not Null Constraints auf eine Tabelle legen:
Constraint wieder löschen:
Nachträglich einen Primärschlüssel anlegen (Achtung es darf keiner bisher existieren):
Nachträglich einen Unique Index anlegen (davon dürfen Sie mehrere auf der gleichen Tabelle besitzen)Hier erlauben wir pro Tag nur einen Mitarbeiter mit gleichem Nachname einzustellen.
Foreign Key Constraint anlegen. (Dieser hat einen Bezug zu einer lokalen Spalte der Tabelle und eine Verbindung zu einer Spalte einer anderen Tabelle)
Der Foreign Key Constraint hat aber noch eine weitere nette Option: On Delete CascadeWenn hier ein Hauptdatensatz (bei uns z.B. die Abteilung) gelöscht wird, werden die Kinddatensätze (hier die Mitarbeiter der Abteilung) auch rekursiv gelöscht
Alternativ kann auch nur die abhängige Spalte auf NULL gesetzt werden
SonderfälleConstraints können auch verzögert geprüft werden. Das ist dann sinvoll, wenn im Datenmodell mit Constraints Änderungen durchgeführt werden sollen, die gegen die Regeln des Constraint verstossen würden.Durch die verzögerte Prüfung erfolgt dies erst beim Commit und nicht schon während der Transaktion.
oder wieder zurück auf Default:
Mit einem ALTER TABLE kann der Zustand der verzögerten Constraints verändert werden:
ENABLE VALIDATE
ENABLE
ENABLE NOVALIDATE
DISABLE NOVALIDATE
DISABLE
DISABLE VALIDATE
Seit einiger Zeit ist die neue Oracle ORDS Version 23.x zum Download verfügbar. Wie heisst ein berühmtes Zitat: Mann muss in einem System jeden Fehler gemacht haben um das System verstanden zu haben. Na dann sind wir kurz davor alles zu wissen :-) …
Laden Sie die Software von Oracle herunter und packen Sie das ZIP File in einem eigenen Ordner aus.
Prüfen Sie nun Ihre installierte Java Version:
Unix / Linux
java --version java 11.0.16.1 2022-08-18 LTS Java(TM) SE Runtime Environment 18.9 (build 11.0.16.1+1-LTS-1) Java HotSpot(TM) 64-Bit Server VM 18.9 (build 11.0.16.1+1-LTS-1, mixed mode)
Das sieht gut aus … OpenJDK wird offiziell von Oracle nicht unterstützt und kann Probleme verursachen! Verwenden Sie Java 11 oder Java 17
Windows:
java.exe --version openjdk 11 2018-09-25 OpenJDK Runtime Environment 18.9 (build 11+28) OpenJDK 64-Bit Server VM 18.9 (build 11+28, mixed mode)
Das ist schlecht, weil Oracle unterstützt wie gesagt keine Java OpenJDK Version. KEINE ! Es kann funktionieren, bei uns trat meist ein Webserver Fehler 500 auf (ohne große Begründung) Unterstützt werden nur die Oracle Java Versionen 11 und 17.
Nach erfolgreicher Installation der Oracle Java Version gehen Sie in den ausgepackten Ordner (z.B. cd c:\temp\ords)
Dort sollte ein “bin” Ordner liegen und da drin eine ords.exe und eine ords Datei
Tragen Sie Java in Ihren Pfad ein:
set PATH=%PATH%;"C:\Program Files\Java\jdk-11\bin"
UNIX:
export PATH=$PATH:/usr/bin/
Wenn Java in Ihrem Pfad eingetragen wurde, starten Sie die Installation mit:
Windows: bin/ords.exe --config c:\oracle\ords install
Tipp: Sie sollten auch nach der Installation des Ords das “bin” Verzeichnis des ORDS und die Datei ords.war nicht wegwerfen. Für nachtägliche Wartungsarbeiten benötigt man die Dateien eventuell nochmal. Sie können die Dateien z.B in den Hauptordner des Config-Verzeichnisses kopieren, also z.B. C:\oracle\ords für Windows, oder /opt/oracle für Linux.
Ab ORDS Version 22.2.x wird der Pfad für den Config Ordner beim Tomcat unter UNIX im Service File eingetragen:
cat /etc/systemd/system/tomcat.service:
… Environment="JAVA_HOME=/usr/lib/jvm/jre" Environment="JAVA_OPTS=-Djava.security.egd=file:///dev/urandom -Dconfig.url=/opt/oracle/ords" …
Windows (wird im Tomcat (tomcat9w.exe) Eigenschaftsfenster Reiter “Java” im Bereich “Java Options” (nicht “Java 9 Options” !!!) eingetragen)
-Dconfig.url=c:\oracle\ords
Unix/Linux:
bin/ords --config /opt/oracle/ords install
Interaktion mit dem Skript:
# bin/ords --config /opt/oracle/ords install ORDS: Release 23.4 Produktion am Mi. Dez 15 06:49:08 2023 Copyright (c) 2010, 2023, Oracle. Konfiguration:/opt/oracle/ords/ Der Konfigurationsordner /opt/oracle/ords enthält keine Konfigurationsdateien. Oracle REST Data Services - Interaktive Installation Geben Sie eine Zahl zur Auswahl des Installationstyps ein [1] ORDS nur in der Datenbank installieren oder upgraden [2] Datenbankpool erstellen oder aktualisieren und ORDS in der Datenbank installieren/upgraden [3] Nur Datenbankpool erstellen oder aktualisieren Choose [2]: Geben Sie eine Zahl zur Auswahl des zu verwendenden Datenbankverbindungstyps ein [1] Basis (Hostname, Port, Servicename) [2] TNS (TNS-Alias, TNS-Verzeichnis) [3] Benutzerdefinierte Datenbank-URL Choose [1]: Geben Sie den Hostnamen der Datenbank ein [localhost]: 172.30.30.141 Listener-Port der Datenbank eingeben [1521]: Datenbankservicename eingeben [orcl]: apex222 Geben Sie einen Datenbankbenutzernamen mit Administratorberechtigungen an. Geben Sie den Administratorbenutzernamen ein: sys Datenbankkennwort für SYS AS SYSDBA eingeben: Verbindung zu Datenbankbenutzer: SYS AS SYSDBA URL: jdbc:oracle:thin:@//172.30.30.141:1521/apex222 wird hergestellt Informationen werden abgerufen. Geben Sie den Default Tablespace für ORDS_METADATA und ORDS_PUBLIC_USER ein [SYSAUX]: Geben Sie den Temporary Tablespace für ORDS_METADATA und ORDS_PUBLIC_USER ein [TEMP]: Geben Sie eine Zahl ein, um zusätzliche Features zum Aktivieren auszuwählen: [1] Datenbankaktionen (aktiviert alle Features) [2] REST-fähige SQL und Datenbank-API [3] REST-fähige SQL [4] Datenbank-API [5] Kein Wert Choose [1]: Geben Sie eine Zahl zum Konfigurieren und Starten von ORDS im Standalone-Modus ein [1] ORDS im Standalone-Modus konfigurieren und starten [2] Überspringen Choose [1]: 2 … INFO: 08:19:07 Validating objects for Oracle REST Data Services. VALIDATION: 08:19:07 Starting validation for schema: ORDS_METADATA VALIDATION: 08:19:07 Validating objects VALIDATION: 08:19:08 Validating roles granted to ORDS_METADATA and ORDS_PUBLIC_USER VALIDATION: 08:19:08 Validating ORDS Public Synonyms VALIDATION: 08:19:08 Total objects: 306, invalid objects: 0, missing objects: 0 VALIDATION: 08:19:08 94 INDEX VALIDATION: 08:19:08 3 LOB VALIDATION: 08:19:08 15 PACKAGE VALIDATION: 08:19:08 14 PACKAGE BODY VALIDATION: 08:19:08 1 PROCEDURE VALIDATION: 08:19:08 52 PUBLIC SYNONYM VALIDATION: 08:19:08 1 SEQUENCE VALIDATION: 08:19:08 32 TABLE VALIDATION: 08:19:08 32 TRIGGER VALIDATION: 08:19:08 20 TYPE VALIDATION: 08:19:08 6 TYPE BODY VALIDATION: 08:19:08 36 VIEW VALIDATION: 08:19:08 Validation completed. INFO: 08:19:08 Completed validation for Oracle REST Data Services. PL/SQL-Prozedur erfolgreich abgeschlossen. Commit abgeschlossen. ------------------------------------------------------------ Containername: APEX222 Skripts für scheduler werden ausgeführt ------------------------------------------------------------ … PL/SQL-Prozedur erfolgreich abgeschlossen. Commit abgeschlossen. 2023-03-15T07:19:15.030Z INFO Installation für Oracle REST Data Services Version 22.4.4.r0411526 wurde abgeschlossen. Verstrichene Zeit: 00:00:27.496 [*** Informationen: Installation für Oracle REST Data Services Version 22.4.4.r0411526 wurde abgeschlossen. Verstrichene Zeit: 00:00:27.496 ] ------------------------------------------------------------ Containername: APEX222 ------------------------------------------------------------ [*** script: ords_configure_gateway.sql] Configured PL/SQL Gateway user APEX_PUBLIC_USER to be proxiable from ORDS_PUBLIC_USER PL/SQL-Prozedur erfolgreich abgeschlossen. 2023-03-15T07:19:15.130Z INFO Konfiguration von PL/SQL-Gatewaybenutzer für Oracle REST Data Services Version 22.4.4.r0411526 wurde abgeschlossen. Verstrichene Zeit: 00:00:00.95 [*** Informationen: Konfiguration von PL/SQL-Gatewaybenutzer für Oracle REST Data Services Version 22.4.4.r0411526 wurde abgeschlossen. Verstrichene Zeit: 00:00:00.95 ]
export DB_PORT=1521 export DB_SERVICE=apex231 export SYSDBA_USER=SYS export SYSDBA_PASSWORD=sys export ORDS_PASSWORD=ords export ORDS_HOME=/opt/oracle/ords export ORDS_CONFIG=/opt/oracle/ords export ORDS_LOGS=$ORDS_CONFIG/logs export PATH=$PATH:$ORDS_HOME/bin
ords --config $ORDS_CONFIG install \ --log-folder $ORDS_LOGS \ --admin-user $SYSDBA_USER \ --db-hostname 127.0.0.1 \ --db-port $DB_PORT \ --feature-db-api true \ --feature-rest-enabled-sql true \ --feature-sdw true \ --gateway-mode proxied \ --gateway-user APEX_PUBLIC_USER \ --proxy-user
Zugriff dann im Browser via: http:server:8080/ords
ords --config $ORDS_CONFIG install \ --db-pool $DB_SERVICE \ --admin-user $SYSDBA_USER \ --db-hostname 127.0.0.1 \ --db-port $DB_PORT \ --db-servicename $DB_SERVICE \ --feature-db-api true \ --feature-rest-enabled-sql true \ --feature-sdw true \ --gateway-mode proxied \ --gateway-user APEX_PUBLIC_USER \ --proxy-user Zugriff dann via: http:server:8080/ords/$DB_SERVICE
set DB_PORT=1521 set DB_SERVICE=apex231 set SYSDBA_USER=SYS set SYSDBA_PASSWORD=sys set ORDS_PASSWORD=ords set ORDS_HOME=c:\oracle\ords set ORDS_CONFIG=c:\oracle\ords set ORDS_LOGS=%ORDS_CONFIG%\logs set PATH=%PATH%;%ORDS_HOME%\bin
ords --config %ORDS_CONFIG% install ^ --log-folder %ORDS_LOGS% ^ --admin-user %SYSDBA_USER% ^ --db-hostname 127.0.0.1 ^ --db-port %DB_PORT% ^ --db-servicename %DB_SERVICE% ^ --feature-db-api true ^ --feature-rest-enabled-sql true ^ --feature-sdw true ^ --gateway-mode proxied ^ --gateway-user APEX_PUBLIC_USER ^ --proxy-user
ords --config %ORDS_CONFIG% install ^ --log-folder %ORDS_LOGS% ^ --db-pool %DB_SERVICE% ^ --admin-user %SYSDBA_USER% ^ --db-hostname 127.0.0.1 ^ --db-port %DB_PORT% ^ --db-servicename %DB_SERVICE% ^ --feature-db-api true ^ --feature-rest-enabled-sql true ^ --feature-sdw true ^ --gateway-mode proxied ^ --gateway-user APEX_PUBLIC_USER ^ --proxy-user
Zugriff dann im Browser via: http:server:80/ords/%DB_SERVICE% Hinweis: der Tomcat Dienst benötigt Leserechte im ORDS Config Verzeichnis !!! icacls %ORDS_CONFIG% /T /grant Benutzer:R
Wir oben beschrieben muss die richtige Java Version installiert worden sein (Oracle Java 11 oder 17) Kann der config Ordner von Oracle/Tomcat Benutzer gelesen werden? Wenn nicht bitte Lese/Schreibrechte an die Dateien vergeben.
Sind alle notwendigen Accounts NICHT gesperrt und stimmt das Passwort ?
select username,account_status,lock_date,expiry_date from dba_users where username like '%PUBLIC%'; USERNAME ACCOUNT_STATUS LOCK_DATE EXPIRY_DATE ------------------------ ------------------ ------------------- ------------------- APEX_PUBLIC_USER LOCKED 15.03.2023 07:57:59 APEX_REST_PUBLIC_USER OPEN 11.09.2024 08:08:32
Das schaut hier nicht gut aus, der Benutzer APEX_PUBLIC_USER ist gesperrt!.
Entsperren mittels:
ALTER USER apex_public_user ACCOUNT UNLOCK IDENTIFIED BY <mein_geheimes_passwort>;
Danach starten wir dem TomCat nochmal durch.
net stop TomCat9 net start TomCat9
Für den Fall, dass Sie das Passwort vom ORDS_PUBLIC_USER in der DB geändert haben und das im ORDS nachtragen möchten:
Für den Default Pool: (wenn der Config Ordner unter /opt/oracle/ords liegt)
ords --config /opt/oracle/ords config --db-pool default secret db.password
Für einen anderen Pool (hier apex231)
ords --config /opt/oracle/ords config --db-pool apex231 secret db.password
Fehlermeldung: Benutzer oder Kennwort für den Verbindungspool namens |default|lo| ist ungültig oder abgelaufen, oder der Account wurde gesperrt
Die naheliegenden Lösungen wären natürlich:
aber in unserem Fall war die Datenbank (pluggable Database Container) im restricted Modus:
Die Lösung war:
alter pluggable database <containername> close immediate; alter pluggable database <containername> open;
Fehlermeldung: Service Unavailable
Request ID: bI7hBYBLvXJ1aZXhH61iMA
Request Timestamp: 2023-10-21T08:58:05.233483445Z
Das Datenbankkennwort-Secret fehlt in dem mit dem Pool |default|lo| verknüpften Wallet
Hier fehlt das Passwort für den ORDS_PUBLIC_USER, oder es ist veraltet oder abgelaufen. Die Lösung unter LINUX ist, das Wallet mit dem Passwort neu anzulegen mittels:
cd /opt/oracle/ords REM dort liegt der Ordner bin aus der Installtion des ORDS!, wenn nicht, gehen Sie bitte in den entsprechenden Ordner sudo bin/ords --config /opt/oracle/ords config secret db.password REM zweimal das Passwort eingeben REM wenn Sie noch weitere Pools besitzen, muss auch hier das Passwort geöndert werden (Pool-Name apex231) sudo bin/ords --config /opt/oracle/ords config --db-pool apex231 secret db.password REM TomCat durchstarten sudo systemctl restart tomcat
Für Windows würde die Lösung so aussehen:
cd c:\oracle\ords bin\ords --config c:\oracle\ords config --db-pool default secret db.password bin\ords --config c:\oracle\ords config --db-pool apex241 secret db.password
Unsere Ordnerstruckur für den Ords sieht wie folgt aus:
Hier war ein falscher Eintrag in der pool.xml Datei (unter Windows z.B. unter c:\oracle\ords\databases) schuld.
Der Parameter plsql.gateway.mode muss auf proxied stehen!
Für Windows:
set ORDS_HOME=c:\oracle\ords set ORDS_CONFIG=c:\oracle\ords %ORDS_HOME%\bin\ords --config %ORDS_CONFIG% config set plsql.gateway.mode proxied
Für Unix
export ORDS_HOME=/opt/oracle/ords export ORDS_CONFIG=/opt/oracle/ords $ORDS_HOME/bin/ords --config $ORDS_CONFIG config set plsql.gateway.mode proxied
Im Logfile des Apache TomCat steht nur:
"GET /ords/wwv_flow.js_messages?p_app_id=4550&p_lang=en&p_version=24.1.5-3518415 HTTP/1.1" 404 451412
Problem war eine falsche Einstellung in der Datei pool.xml (z.B. unter c:\oracle\ords\databases\default):
dort musste
<entry key="plsql.gateway.mode">disabled</entry>
durch
<entry key="plsql.gateway.mode">proxied</entry>
ersetzt werden.
Wir hatten kürzlich das Problem, das keine Applikationen mehr importiert werden konnten. Beim Auswählen der Datei kam im nächsten Schritt die Fehlermeldung, dass keine Datei ausgewählt wurde.
Das Problem war hier, dass beim Benutzer FLOWS_FILES einige Indizes defekt waren. Nach einem Rebuild war ein Import wieder möglich.
Der folgende Select schreibt Ihnen ein Skript, um defekte Indizes zu finden und reparieren.
select 'ALTER INDEX '||owner||'.'||index_name||' REBUILD;' as sql_stmt from dba_indexes where (owner='FLOWS_FILES' or owner=(select schema from dba_registry where comp_id='APEX')) and status='UNUSABLE';
Bei der Migration auf einen anderen Server hatten wir plätzlich beim start des Workspace den Fehler:
Die Anforderung kann nicht verarbeitet werden, da diese Ressource keine Cross Origin Sharing-Anforderungen unterstützt oder da der Anforderungsursprung nicht autorisiert ist, auf diese Ressource zuzugreifen. Wenn ords als Reverse-Proxy verwendet wird, stellen Sie sicher, dass der Frontend-Server den Hostnamen propagiert. Stellen Sie für mod_proxy sicher, dass "ProxyPreserveHost" eingeschaltet ist.
Die Lösung bestand darin in die die Datei /etc/httpd/conf/httpd.conf (bzw. eine Unterdatei z.B. in conf.d) um folgenden Eintrag zu ergänzen:
RequestHeader unset Origin
Mehr Tipps & Tricks erfahren Sie in unserem Oracle ORDS und im APEX II Kurs. Wir freuen uns auf Sie!
Haben Sie sich auch schon darüber geärgert, dass gerade Oracle keine Boolean Datentypen in SQL erlaubt?Wenn Sie also eine PL/SQL Funktion besitzen, die nur TRUE oder FALSE zurückgibt, muss man sich einen Wrapper in PL/SQL schreiben.
Aber in unserem Tipp des Monats, bekommen wir das mit einem Trick auch nur in SQL hin.
Sagen wir mal, wir hätten eine Funktion wie diese hier:
Dann könnten wir mit einer einfachen WITH Klausel das auch in reinem SQL hinbekommen.
Viele weitere Tipps & Tricks bekommen Sie in einem unserer bewährten PL/SQL Kurse (PL/SQL, PL/SQL II, PL/SQL Packages, ...)
Ich liebe das Package dbms_output, wenn es nur nicht ...
hätte.
Aber den letzen Punkt können wir ändern. In diesem Tipp holen wir die Daten, die wir in den Puffer von dbms_output geschrieben haben und legen Sie woanders hin.
##################################################Umleitung von dbms_output zu pipe##################################################
CREATE OR REPLACE PROCEDURE get_dout_from_pipe (pipe_name IN VARCHAR2 DEFAULT 'DBMS_OUTPUT_PIPE')
IS
v_message VARCHAR2(32767);
v_timeout NUMBER:=120;
BEGIN
IF (DBMS_PIPE.receive_message(pipe_name,v_timeout)) <> 0 THEN
RAISE_APPLICATION_ERROR(-20501,'Fehler beim Lesen aus Pipe '||pipe_name||' aufgetreten !');
END IF;
LOOP
EXIT WHEN DBMS_PIPE.NEXT_ITEM_TYPE = 0;
DBMS_PIPE.unpack_message(v_message);
DBMS_OUTPUT.PUT_LINE(v_message);
END LOOP;
END;
/
##################################################Umleitung von dbms_output zu htp##################################################
CREATE OR REPLACE PROCEDURE test_ausgabe IS PROCEDURE dop2htp IS lines dbms_output.chararr; num_lines number:=1000000; BEGIN dbms_output.get_lines(lines, num_lines); FOR i IN 1..num_lines LOOP htp.p(lines(i)||'<BR>'); END LOOP; END; BEGIN dbms_output.enable(null); FOR i IN 1 .. 10 LOOP dbms_output.put_line('Zeile='||i); END LOOP; dop2htp; -- <=######## Umwandelung von dbms_output in htp.p Ausgabe END;
Ich hoffe dies konnte Ihnen weiterhelfen, bei sonstigen Fragen melden sie sich gerne bei uns und oder besuchen sie einen der Kurse. :-)
Firmen, die mit personenbezogenen Daten arbeiten, sind gesetzlich zum Audit verpflichtet. In der Praxis sieht das allerdings häufig so aus, dass man im Vertrauen darauf, dass die Default-Audit Einstellungen von Oracle schon alles Wesentliche abdecken werden, die Inhalte der Audit-Trails eine bestimmte Zeit aufhebt und dann löscht oder irgendwohin exportiert, ohne jemals einen Blick auf den Inhalt geworfen zu haben.
Und wenn ein entnervter DBA unter Oracle 11g kurz nachsehen will, welcher xxxxx an den Datenbankparametern gedreht hat und es wieder mal keiner gewesen sein will, wird er im Audit-Trail der Datenbank vergeblich danach suchen, selbst wenn er den Parameter AUDIT_SYS_OPERATIONS auf TRUE gesetzt hat. Unter Linux müsste er dazu unzählige aud-Files im Betriebssystem und unter Windows das Eventlog durchforsten.
Um wirklich das auditiert zu bekommen, was man gerne hätte und die Auswertung nicht allzu zeitraubend zu gestalten, muss man die Audit-Einstellungen und das Housekeeping der Daten manuell einrichten und testen. Auch die Übertragung eines fertigen 11g-Audit-Konzepts auf Oracle 12c ist eine Menge Arbeit. Dieser Vortrag beschäftigt sich anhand eines fiktiven, aber nicht untypischen Szenarios mit den Schwachstellen der Default-Audit-Konfiguration in Version 11g und 12c und stellt Lösungsansätze für das Audit vor, mit denen man die Erfassung der Daten und die Auswertung vereinfachen kann.
AUSGANGSLAGE FÜR DAS AUDIT-SZENARIODer neue, motivierte und experimentierfreudige DBA einer mittelständischen Firma soll ein neues Audit-Konzept umsetzen. Im Einsatz sind Oracle-Datenbanken der Version 11.2.0.4 (Standard Edition One) auf Linux und auf Windows. Alle Angestellten der Firma loggen sich unter dem selben Account , aber von unterschiedlichen Rechnern aus ein und können entweder direkt (über SQL Developer) oder über ein APEX-Interface auf die Tabellen zugreifen. Der DBA-Kollege nutzt manchmal auch den Enterprise Manager. Die DBAs arbeiten als SYSDBA auf der Instanz, alle anderen haben die Rollen CONNECT und RESOURCE.
Auditiert werden sollen:
Weitere Forderungen
PROBLEME BEI EINRICHTUNG, AUSWERTUNG UND HOUSEKEEPING DES AUDITS UNTER 11G
Gewöhnungsbedürftige Syntax für das Einrichten der Audit-OptionenVon den oben geforderten Audits wird nur ein kleiner Teil über die Default-Einstellungen abgedeckt. Es ist also viel Handarbeit nötig, wobei die Syntax der AUDIT-Anweisung einige Fallstricke enthält.So kann z.B. ein unvorsichtiges SELECT TABLE BY <username> den Audit-Trail exponentiell aufblasen, wenn man ein Tool wie den SQL Developer benutzt.
Überflüssige Informationen im Audit-TrailWenn man den Enterprise Manager konfiguriert hat, der sich im Sekundentakt bei der Datenbank anmeldet, führen die Default-Einstellungen dazu, dass der Audit-Trail größtenteils mit den Logon- und Logoff-Einträgen der User SYSMAN und DBNSMP gefüllt wird. Beim SYS-Auditing werden unter 11g alle Statements aufgezeichnet. Hier muss man den Overhead der Data-Dictionary-Zugriffe (recursive SQL) beim Auswerten herausfiltern. Auch der RMAN erzeugt eine Flut von Einträgen, wenn er sich als SYSDBA anmeldet.
Unterschiedliche Speicherorte der verschiedenen Audit-InformationenConnects als SYSDBA bzw. SYSOPER, Stops und Starts der Datenbank werden per default auditiert (mandatory auditing). Alle weiteren Aktionen des Users SYS können durch Umstellung des Parameters AUDIT_SYS_OPERATIONS auf TRUE auditiert werden. Unter Unix werden die Informationen jedoch in das durch den Parameter audit_file_dest angegebene Verzeichnis geschrieben, unter Windows ins Eventlog. Um dieses Audit auswerten zu können, müsste man die Inhalte der *.aud-Files unter Linux bzw. die Oracle-spezifischen Inhalte des Eventlogs unter Windows parsen und in die Datenbank laden. Beides ist möglich, aber aufwendig.
Unzulänglichkeiten des Packages DBMS_AUDIT_MGMTDas Package DBMS_AUDIT_MGMT ist umständlich zu bedienen, vor allem, wenn man sowohl in der Datenbank als auch im Filesystem aufräumen will. Um die Einträge im Windows Event Log muss man sich selber kümmern.
VORSCHLAG FÜR EIN "UNIFIED AUDITING" ab 11GWenn man den Parameter AUDIT_TRAIL auf XML setzt, werden alle zu auditierenden Statements des Standard, Mandatory, SYS- und Fine Grained Auditing (letzteres natürlich nur in der Enterprise Edition) im AUDIT-FILE-DEST-Verzeichnis als XML-Files gespeichert und können über die View V$XML_AUDIT_TRAIL gemeinsam ausgewertet werden, ähnlich wie die XML-Files des Alert.logs über die View V$DIAG_ALERT_EXT. Die seit der Oracle-Version 10.2 verfügbare View DBA_COMMON_AUDIT_TRAIL vereint diese Einträge mit denen aus DBA_AUDIT_TRAIL und DBA_FGA_AUDIT_TRAIL, so dass auch die Inhalte der Tabellen AUD$ und FGA_LOG$ noch sichtbar bleiben. Diese Lösung kann man durchaus als abgespecktes "Unified Auditing" für 11g bezeichnen. Die Auswertung und das Housekeeping werden dadurch wesentlich erleichtert. Auch die Performance des Audits leidet nicht darunter, dass man die Audit-Files im Betriebssystem speichert , eher im Gegenteil. Wenn man den XML-Audit-Trail vor Zugriffen durch übel gesinnte DBAs schützen will, muss man dafür sorgen, dass die Files in kurzen Abständen auf einen anderen Server außer Reichweite gesichert werden.
Im Vortrag wird gezeigt, wie man die oben genannten Anforderungen an das Audit mit dieser Methode, ein paar Views für die bequeme Auswertung und einem datenbankgesteuerten Housekeeping umsetzen kann.
UND WIE SIEHT'S UNTER 12C AUS ?Unsere mittelständische Firma wächst und gedeiht und denkt an einen Upgrade auf die Version 12c.
Das unter 12c neu eingeführte Unified Auditing soll schneller, leichter einzurichten und zu verwalten und für alle Editions verfügbar sein.Im Prinzip ja, aber ...
Die Standard Edition One (SEO) gibt es nur noch in der Version 12.1.0.1. Hier ist das Feature wegen des Bugs 17466854 (CANNOT SET UNIFIED AUDITING IN STANDARD EDITION) nicht zu aktivieren. Dafür gibt es einen Patch 17466854, den man aber nicht einspielen kann, wenn man seine Datenbank mit dem aktuellen Patchset versorgt hat. Der Bugfix wurde für den Patchset 12.1.0.1.5 (vom 14.10.2014) geschrieben und funktioniert nicht für höhere Levels. Für SEO-Datenbanken unter Windows soll der Bugfix im Patchset 12.1.0.1.18 eingeschlossen sein.
Da die SEO allerdings sowieso ein Auslaufmodell ist, steigt unsere Firma doch lieber auf die Standard Edition 2 (SE2) um. Bei der Version 12.1.0.2 funktioniert der Umstieg auf Unified Auditing problemlos. Es macht sich jedoch deutlich bemerkbar, dass bei jedem Patch diverse Bugs gefixt werden. Man sollte also unbedingt die neuesten Patches einspielen !
Nach der Migration auf die Version 12c ist zunächst der sogenannte Mixed Mode aktiv, unter dem nur die Policies ORA_SECURECONFIG und zusätzlich ORA_LOGON_FAILURES (erst ab 12.1.0.2) aktiviert sind. Diesen beizubehalten, ist keine wirklich gute Option, vor allem hinsichtlich des Housekeepings und der Sicherheit der Audit-Daten gegenüber Manipulation durch den DBA. Zudem gibt es einige wirklich nützliche zusätzliche Features beim neuen Unified Auditing, die man sich nicht entgehen lassen sollte. Dazu zählt vor allem die größere Sicherheit der Audit-Daten.
WAS IST BEIM UMSTIEG AUF UNIFIED AUDITING UNTER ANDEREM ZU BEACHTEN ?
Das sys-Audit ist nicht mehr das, was es einmal warÄnderungen am System, an den Audit-Einstellungen etc. werden im Unified Auditing immer auditiert, egal, ob man sich als SYSTEM oder SYS AS SYSDBA, SYSOPER, SYSDG, SYSBACKUP bzw. SYSKM anmeldet.Ansonsten wird der User SYS aber genauso behandelt wie Hinz und Kunz !!! Auch seine Selects erscheinen nicht mehr im Audit-Trail. Wenn man z.B. mitbekommen will, ob er sich per DML an irgendwelchen User-Tabellen vergreift, muss man dieses Audit explizit in einer Policy einrichten! Der Parameter AUDIT_SYS_OPERATIONS hat keinen Einfluss mehr.
Per Default werden nur failed logins auditiertDass nicht mehr jeder LOGON und LOGOFF registriert wird, macht den Audit-Trail zwar übersichtlicher, aber für Auswertungen des Audit-Trails hinsichtlich der Dauer der Sessions oder der Anzahl nicht korrekt beendeter Session (LOGOFF BY CLEANUP) muss man sich nun eigene Policies schreiben.
Die alten Audit-Optionen sind nicht 1:1 in den neuen Policies abzubildenEin AUDIT PROCEDURE BY consultant;unter 11g wird unter 12c zuCREATE AUDIT POLICY consultant_plsql_polACTIONS CREATE FUNCTION, DROP FUNCTION, CREATE LIBRARY, DROP LIBRARY, CREATE PACKAGE, DROP PACKAGE, CREATE PACKAGE BODY, CREATE PROCEDURE, DROP PROCEDURE;AUDIT POLICY consultant_plsql_pol BY consultant;
Das ist eigentlich ein Vorteil, weil diese Syntax besser verständlich ist, aber die Policies können schnell unübersichtlich werden. Die Anforderungen an das Audit von Seite 1 lassen sich über die beiden Default-Policies und 3 zusätzliche maßgeschneiderte Policies verwirklichen. Zuviel Policies wirken sich eher schädlich auf die Performance aus.
Das neue Audit ist per Default "extended"Während man unter der Version 11g den Parameter audit_trail auf DB, extended oder XML, extended setzen musste, um auch die SQL-Statement und Bindvariablen zu erfassen, ist das in Version 12c per Default der Fall. Das lässt den Audit Trail entsprechend schnell anwachsen, wenn die Statements etwas komplexer werden. Auch das obligatorische RMAN-Audit braucht einiges an Platz. Deshalb ist ein durchdachtes Housekeeping fast noch wichtiger als unter 11g.
Wie der (immer noch motivierte) DBA den Umstieg von der selbstgestrickten Unified Auditing Lösung unter 11g auf die Audit-Konfiguration unter 12c meistert und was ein vernünftig konfiguriertes Audit alles an Verbrechen gegen die Datenbank im allgemeinen und die guten Sitten im besonderen zu Tage fördern kann, erfahren Sie im Vortrag.
Oracle hat das Berechtigungskonzept zu PL/SQL in Hinblick auf zwei gegensätzliche Szenarien in 12c ausgebaut:
Die Änderung zu diesem Szenario (Vergabe von Rollen) betrifft Prozeduren, die mit Invoker Rights arbeiten oder mit dynamischem SQL.
Beiden Neuerungen gemeinsam ist, dass es um die Überprüfung von Rechten zur Laufzeit geht. Auch weiterhin benötigt ein Entwickler alle entsprechenden Berechtigungen selber, um eine Prozedur erfolgreich kompilieren zu können. Dynamisches SQL allerdings wird zur Kompilierzeit nicht ausgewertet.
Hinweis: Hier und im weiteren ist "Prozedur" als Sammelbegriff zu verstehen, der auch Funktionen und Packages mit einschließt.
Hier kommt Szenario 1 ins Spiel:
Angenommen, der User ADMIN hat weitreichende Rechte.
Weiter angenommen, der Programmierer SCOTT hat vergleichsweise wenig Rechte.
Nun schreibt SCOTT eine Prozedur mit Invoker Rights (bei Definer Rights spielt das neue Privileg keine Rolle), die er ADMIN zur Verfügung stellt. Solange es sich um statisches SQL handelt, kann nicht viel passieren, da ja SCOTT's Berechtigungen zur Compile-Zeit überprüft werden.
Nun könnte aber SCOTT bösartigerweise Befehle in dynamisches SQL verpacken, die weit über seine eigenen Berechtigungen hinausgehen (z. B. an sich selbst Admin-Rechte vergeben), nicht jedoch über diejenigen von ADMIN. SCOTT kann so eine Prozedur problemlos erstellen - aber nicht ausführen. ADMIN dagegen kann sie ausführen.
Um einen solchen Missbrauch ggf. unterbinden zu können, wurde mit Version 12c die Berechtigung INHERIT [ANY] PRIVILEGES eingeführt. Das Konzept dabei sieht folgendermaßen aus:
Der Eigentümer der Prozedur (in obigem Szenario SCOTT) braucht, sofern er nicht über das Systemprivileg INHERIT ANY PRIVILEGES verfügt, von dem Benutzer, der die Prozedur später ausführen soll - also hier ADMIN - , das Objektprivileg INHERIT PRIVILEGES. Hat er das nicht, so kann ADMIN später die Prozedur nicht ausführen.
Damit sich das Verhalten zwischen 11g und 12c nicht ändert, erhält PUBLIC automatisch für jeden neu angelegten User dieses Recht. Das können Sie leicht nachprüfen über dba_tab_privs:
Oracle empfiehlt jedoch PUBLIC diese Rechte zu entziehen.
Für das oben beschriebene Szenario bedeutet dies:
Hat PUBLIC das Recht INHERIT PRIVILEGES ON USER ADMIN, wie das dem Default entspricht, so wird ADMIN die Prozedur von SCOTT ausführen können, wie auch schon in 11g. Entzieht ADMIN dieses Recht mit
und vergibt das Recht auch nicht explizit an SCOTT, dann kann er keine Prozedur von SCOTT mehr ausführen, die mit INVOKER RIGHTS angelegt wurde. Beim Versuch erhält er die Fehlermeldung
Szenario 2 sieht so aus:
User SCOTT stellt wiederum Invoker Rights-Prozeduren zur Verfügung, in diesem Fall für den User LEHRLING. Eine der Prozeduren greift auf ein Tabelle im Schema SCOTT zu. SCOTT will aber nicht, dass LEHRLING direkten Zugriff auf diese Tabelle bekommt. Den bräuchte LEHRLING aber bis einschließlich Version 11g, um diese Prozedur ausführen zu können.
SCOTT erstellt z. B. folgende Funktion:
LEHRLING wird diese Funktion bis jetzt nicht erfolgreich ausführen können:
In Version 12c stellt nun ein DB-Administrator SCOTT eine Rolle zur Verfügung:
SCOTT vergibt das benötigte Select-Recht and die Rolle:
Und die Rolle an die Funktion(!):
Nun kann LEHRLING die Funktion erfolgreich ausführen ohne direkten Zugriff auf SCOTT.dept zu erhalten.
An dem Grundprinzip, dass Rollen in PL/SQL unwirksam sind, ändert sich nichts: Eine Prozedur kann auch weiterhin nur dann erfolgreich kompiliert werden, wenn ihr Eigentümer alle dafür erforderlichen Rechte DIREKT gegrantet bekommen hat.
Ein Beispiel zur Anwendung dieses Rollenkonzepts bei Definer Rights und dynamischem SQL hat Tom Kyte in seinem Blog beschrieben.
Letztens bin ich über ein vermeintlich trivales Problem gestolpert: Ich wollte die Größe einer Tabelle berechnen. Nur war die vermeintlich nur sehr klein. Wo lag das Problem?
Wenn man in USER_SEGMENTS oder DBA_SEGMENTS nachschaut, steht dort beim Tabellen (Segment) Namen nur die Größe der Basistabelle (ohne Lob Spalten)
Als Eigentümer des Objekts kann man folgenden Befehl absetzen:Hinweis: Ändern Sie bitte in der ersten Zeile den Namen der Tabelle ab.
Das Ergebnis könnte dann z.B so aussehen:
Wenn man als DBA das Ganze ansehen möchte:
Hatten Sie auch schon einmal den Wunsch, den Anwendern einer Applikation etwas mitzuteilen? Und wäre es nicht manchmal gut, wenn jeder Anwender nachweislich die Information gelesen hat? Die Informationen sollen sofort, also auch in einer laufenden Session, in einem modalen Popup- Fenster angezeigt werden. Dieses Problem stellte sich vor einiger Zeit in einem APEX-Projekt und aus diesem Grund haben wir ein Informationssystem für APEX-Anwendungen entwickelt.
Um die Anforderungen abzudecken brauchen wir im ersten Schritt zwei Tabellen. In der ersten werden die "Nachrichten" gespeichert, in der zweiten die Information, wer wann das Lesen bestätigt hat.
CREATE TABLE INFORMATIONEN ( ID NUMBER, -- Eindeutige ID, Trigger und Sequence APP_ID NUMBER, -- Applikations ID der Apexanwendung STATUS CHAR(1), -- A für aktiv oder I für inaktiv INFORMATION VARCHAR2(500), -- Freitext für die Informationsn CONSTRAINT PK_INFORMATIONEN PRIMARY KEY (ID) );
CREATE TABLE INFORMATION_READ ( INFO_ID NUMBER, -- ID der Information die gelesen wurde APP_USER VARCHAR2(30), -- Welcher User hat gelesen READ_DATE DATE -- Wann wurde gelesen, Trigger mit SYSDATE );
Der nächste Schritt ist, eine Seite in der Applikation zu erstellen auf der die Informationen angezeigt werden sollen. Als Template wählen wir Popup. Im Bereich "Page HTML Body Attribute" kommt noch folgende Anweisung dazu:
Jetzt sollte man sich auch überlegen wie viele Informationen gleichzeitig angezeigt werden müssen. Entsprechend viele Items müssen erzeugt werden.Wir benötigen je Info ein "Display only" Item (PX_INFOTEXT_X). Dabei sollte beachtet werden, dass die Eigenschaft "Escape special characters" auf NO steht, dadurch können HTML Formatierungen in den Text integriert werden. Zu jedem Infotext kommt noch eine Checkbox (return 1 when checked), damit können die Nachrichten einzeln bestätigt werden. Infotext und Checkbox werden nur angezeigt, wenn Infotext "NOT NULL" ist. Schließlich fehlt noch je ein Hidden Item zum Speichern der ID und ein Button zum Bestätigen der Seite.
Jetzt fehlen noch zwei Prozesse, der erste "On Load - Before Header" mit dem die Inhalte gefüllt werden:
declare v_cnt number := 1; v_trenner varchar2(30) := '<p><hr><p>'; begin for rec in (select id, information from informationen where app_id = :APP_ID and status = 'A' and id not in (select info_id from information_read where app_user = :APP_USER) order by id) loop if v_cnt = 1 then :PX_ID1 := rec.id; :PX_INFOTEXT_1 := rec.information; end if; if v_cnt = 2 then :PX_ID2 := rec.id; :PX_INFOTEXT_2 := rec.information; end if; v_cnt := v_cnt + 1; end loop; end;
Dann kommt der Prozess zum Speichern der Informationen, wenn der Button gedrückt wurde:
begin if :PX_CHECK1 = 1 then insert into information_read values(:PX_ID1, :APP_USER, SYSDATE); end if; if :PX_CHECK2 = 1 then insert into information_read values(:PX_ID2, :APP_USER, SYSDATE); end if; :FXXX_HIDE := 'TRUE'; :FXXX_INFO := '0'; end;
Hier tauchen erstmals die Applikations Items FXXX_HIDE und FXXX_INFO auf. Diese werden für die Steuerung des Infofensters benötigt. Bei Betätigung des Buttons wird auf jeden Fall das Item HIDE auf TRUE gesetzt, damit wird eine weitere Anzeige innerhalb der gleichen Session verhindert. Die Nachrichten können separat bestätigt werden, das heißt der Anwender kann entscheiden, ob sie in der nächsten Session wieder erscheinen sollen.
Nachdem es sich um ein modales Popup-Fenster handelt brauchen wir noch einen Branch, um es nach der Verarbeitung zu schließen. Der Branch Typ ist "Branch to PL/SQL Procedure".
begin htp.p('<body>'); htp.p('<script type="text/java-script">'); htp.p('parent.$("#modalDialog").dialog("close");'); htp.p('</script>'); htp.p('</body>'); end;
Kommen wir nun zur Steuerung. Bedingung war ja, dass es auch in einer laufenden Session erscheinen soll. Dafür müssen wir bei jedem Neuladen einer Seite nachsehen, ob es eine Nachricht gibt die der jeweilige User noch nicht gelesen hat. Weiterhin soll es die Möglichkeit geben, das modale Fenster zu schließen ohne die Nachrichten zu bestätigen. Dafür werden die Applikationsitems FXXX_HIDE und FXXX_INFO angelegt.Dazu gehört auch ein Applikations Prozess mit dem Zündpunkt "On Load: Before Header".
begin select count(*)into :FXXX_INFO from informationen where app_id = :APP_ID and status = 'A' and id not in (select info_id from information_read where app_user = :APP_USER); end;
Jetzt der zentrale Punkt: wann und wie zeige ich das modale Fenster an!
Dazu wird auf der Seite 0 eine "Dynamic Action" mit folgenden Einstellungen angelegt.
When: Event = Page Load Condition = No Condition Advanced: Event Scope = once Condition: Type = PL/SQL Expression Expression1 = NVL(:FXXX_HIDE,'F') != 'TRUE' and :FXXX_INFO > 0 and :APP_PAGE_ID not in (101,X)
Es müssen Loginseite und die Seite die als Popup erscheint ausgeschlossen werden.
TRUE ACTION: Execute Java-ScriptCode (In diesem Beispiel wird in der Applikation 100 die Seite 7 als modales Popup aufgerufen) var ev = this.browserEvent; ev.preventDefault; var horizontalPadding = 20; var verticalPadding = 20; $('<iframe id="modalDialog" src="f?p=100:7:&APP_SESSION.::NO::" />').dialog( {title: "APEX System Info", autoOpen: true, width: 700, hight: 350, modal: true, close: function(event, ui) { $(this).remove();}, overlay: {opacity: 0.5, background: "black"} } ).width(700 - horizontalPadding).height(350 - verticalPadding); return false;
Der Anwender bekommt "neue Informationen" auch während einer laufenden Session sofort angezeigt und er muss aktiv werden und die Meldungen bestätigen, um sie dauerhaft auszublenden.
Achtung! Ab der APEX Version 4.1 sind aus Sicherheitsgründen Frames per default nicht erlaubt. Damit dieses Beispiel funktioniert muss in den Security Attributen "Embed in Frames" auf "Allow from same origin" umgestellt werden.
Weitere Informationen und Tipps zur Entwicklung mit APEX bekommen Sie auch in unseren Schulungen Entwicklung mit Application Express.
Ab Version 12c können Spalten ausgeblendet werden, indem man sie als "invisible" deklariert. Das ist sowohl beim Anlegen einer Tabelle oder Spalte möglich als auch nachträglich.Das bedeutet aber nicht, dass auf eine solche Spalte nicht zugegriffen werden kann, sondern nur, dass sie ohne Angabe einer expliziten Spaltenliste nicht berücksichtigt wird:
Solange man die Spalte explizit anspricht, kann man also ganz normal mit ihr arbeiten.
Interessant ist, dass TOAD die Spalte beim DESCRIBE mit angibt - und an welcher Position:
Hier lohnt sich ein Blick ins Data Dictionary:
Die column_id ist also bei unsichtbaren Spalten nicht gefüllt. Interessanter noch ist die etwas weniger bekannte user_tab_cols:
Wenn eine unsichtbare Spalte wieder sichtbar gemacht wird, bekommt sie grundsätzlich die höchste column_id und rückt dementsprechend ans Ende der Spaltenliste:
Auf diese Art könnte man beispielsweise auch eine neu eingefügte Spalte, die ja bis 11g grundsätzlich als letzte Spalte angezeigt wird, in der Spaltenliste weiter nach vorne wandern lassen:
So ganz neu ist das Konzept der unsichtbaren Spalten nicht. Haben Sie sich schon einmal angeschaut, wie eine Spalte vom Typ XMLTYPE intern dargestellt wird?
Hier kann die unsichtbare Spalte SYS_NC00006$ prinzipiell auch direkt angesprochen werden. Da es sich aber bei Speicherung des XMLTYPE als binary xml (dem Default in 12c) um einen BLOB handelt, ist das allerdings nicht sehr sinnvoll. Und bei Speicherung als CLOB (deprecated in 12c) bietet es zumindest keine Vorteile.
Das Prinzip ist also ähnlich, auch wenn es offensichtlich Unterschiede im Detail gibt. Interessierte sollten sich die Spalten column_id (hier gefüllt!), segment_column_id, virtual_column und - in Version 12c neu eingeführt - user_generated in user_tab_cols genauer anschauen.
Sie würden gerne wissen, was ist alles neu in 12c? - dann schauen Sie doch in unserer Oracle Schulung Neuerungen 12c vorbei.
Die Erstellung von Statistiken über Datenbank-Objekte wie Tabellen oder Indizes ist seit der Einführung des kostenbasierenden Optimizers ein absolutes Muss. Die Qualität der Statistiken entscheidet darüber, ob ein SQL-Statement performant in der Datenbank verarbeitet werden kann oder nicht. Mit Hilfe der Statistiken bestimmt die Datenbank, welche Kosten im Sinne von Ressourcen-Nutzung entstehen und welcher Zugriffs-Pfad zu den geringsten Kosten führt.
Der vorliegende Monatstipp hat nicht das Ziel einer detaillierten Beschreibung des kostenbasierenden Optimizers. Dazu wird auf unsere Muniqsoft-Training-Schulungen und auf die einschlägige Literatur verwiesen.
Vielmehr werden folgende Fragestellungen näher betrachtet:
Seit Einführung der RDBMS-Version 10g existiert ein automatischer Statistik-Erstell-Job, der für alle Tabellen, die entweder keine oder veraltete (Stale) Statistiken aufweisen, Statistiken erstellt. Die verwendete Prozedur heißt „DBMS_STATS.GATHER_DATABASE_STATS_JOB_PROC“ und verwendet die gleichen Default-Parameter wie die „DBMS_STATS.GATHER_*_STATS“-Prozedur. Per Default werden die Statistiken aller Tabellen, deren Datensätze sich zu 10% geändert haben, als veraltet (stale) betrachtet und somit neu erstellt. Dieser Wert ist bis Oracle Version 10.2 fest und kann nicht geändert werden. Wenn die Notwendigkeit besteht, Statistiken für eine Tabelle öfters erstellen zu lassen, gibt es ab Version 11.1 die Prozedur „DBMS_STATS.SET_TABLE_PREFS“.
Z.B. kann die Tabelle „SCHULUNG“ des Users „MQS“ bereits bei 5% Änderungen folgendermaßen als veraltet deklariert werden und somit die Erstellung von Statistiken erzwungen werden:
Wenn das automatische Erstellen von Statistiken nicht gewünscht wird, weil z.B. eine andere Prozedur dies bereits erledigt, kann der Automatismus folgendermaßen nur auf Erstellung der Data Dictionary-Tabellen eingeschränkt werden:
Für die manuelle Erstellung von Statistiken ist grundsätzlich das PL/SQL-Package DBMS_STATS und nicht mehr das ANALYZE-Kommando zu verwenden.
Bei der DBMS_STATS-Prozedur sollen die beiden Parameter ESTIMATE_PERCENT und METHOD_OPT näher betrachtet werden:
ESTIMATE_PERCENT gibt den prozentualen Wert an, wieviele Datensätze einer Tabelle als Basis für die Statistikerstellung herangezogen werden. Je höher der Wert, desto genauer die Statistik, aber desto höher auch die Ausführungszeit der Statistikerstellung. Ab 10g hat sich der Default-Wert für estimate_percent von 100% auf AUTO_SAMPLE_SIZE geändert. Hierbei entscheidet die Datenbank selbst über das Verhältnis von untersuchten Datensätzen zur Erzielung brauchbarer Statistiken und der möglichst geringen Systembelastung bedingt durch deren Erstellung. Leider hat sich bei 10g gezeigt, dass die Anzahl der untersuchten Datensätze zu gering war und deswegen ein absoluter Wert für ESTIMATE_PERCENT sinnvoller war.
Mit Version 11g hat Oracle den Algorithmus für AUTO_SAMPLE_SIZE geändert. Der Effekt ist, dass 100% der Datensätze untersucht werden, aber nur eine Systembelastung wie bei einem Sample von ca. 10% zu verzeichnen ist.
Die Empfehlung ist daher bei der Statistik-Erstellung von Tabellen einer 11g-Datenbank für ESTIMATE_PERCENT den AUTO_SAMPLE_SIZE Parameter zu verwenden.
Mit dem Parameter METHOD_OPT kann definiert werden, ob sogenannte Histogramme für Tabellenspalten erzeugt werden. Histogramme teilen dem Oracle Optimizer mit, wie die Werte in den Spalten verteilt sind – z. B. wie oft der Wert „Müller“ in der Spalte „KD_NAME“ enthalten ist. Je öfter der Wert vorhanden ist, desto eher kann sich der Oracle Optimizer dazu entschließen, anstatt einem Direkt-Zugriff über Index alle Datensätze der Tabelle mit einem Full Table Scan zu lesen.
Bei Datenbanken der Version 10g trat bei Verwendung von Histogrammen der sogenannte „Bind-Peeking“-Effekt ein, bei dem Oracle auf Grund des ersten Wertes einer Spalte in der „where“-Klausel einen Ausführungsplan gewählt hat (z.B. ein Full Table Scan, weil der Wert sehr häufig vorkam) und bei der nächsten Ausführung trotz eines Wertes mit geringerer Selektivität (Wert kommt seltener vor) den Ausführungsplan nicht geändert hat.
Um diesen Effekt bei Version 10g zu verhindern gibt es zwei Möglichkeiten:
Wenn in der Applikation aussschließlich Bind-Variablen verwendet werden, sollten die Histogramme gelöscht werden:
Nach Ausführen der folgenden Prozedur erstellen sowohl der automatische Statistik-Erstell-Job als auch die DBMS_STATS.GATHER_*_STATS-Prozeduren keine Histogramme mehr.
Wenn die Applikation auch Literale verwendet, ist das Ausschalten des Bind-Peekings die bessere Methode.
Bitte vor Setzen des sogenanten Underscore-Parameters in MyOracleSupport über mögliche Seiteneffekte informieren oder beim Oracle Support nachfragen.
Mit Version 11g ist das sogenannte „Adaptive Cursor Sharing“ zur Verhinderung des Bind-Peekings eingeführt worden. Vereinfacht gesprochen können bei diesem Konzept mehrere Ausführungspläne für ein SQL-Statement bei Vorlage unterschiedlicher Verteilungen in den Bind-Variablen erstellt werden.
Die Empfehlung bei 11g für den Parameter METHOD_OPT ist der Default-Wert mit Erstellung von Histogrammen.
Eine weitere Option, die beim Erstellen von Statistiken beachtet werden kann, sind „Pending Statistics“. Wenn man vom Default abweichende Angaben bei der Erstellung von Statistiken gemacht hat, können diese innerhalb der eigenen Session ohne Beeinflussung des Gesamtsystems als „nicht zu veröffentlichen“ deklariert werden.
Mit Hilfe des Session-Parameters “OPTIMIZER_USE_PENDING_STATISTICS“ = TRUE werden die erstellten Statistiken innerhalb der Session verwendet. Wenn die Statistiken akzeptiert werden sollen, können sie „veröffentlicht“ werden und gelten damit für das Gesamtsystem.
Die Datenbank erstellt seit Version 10g automatisch im Rahmen eines Maintenance-Windows (werktäglich um 22 Uhr, Samstag und Sonntag um 6 Uhr bei 11g ) Statistiken für alle Tabellen, die keine oder veraltete Statistiken haben.
Wenn der Zeitpunkt nicht erwünscht ist, kann die Statistikerstellung folgendermaßen deaktiviert
oder verschoben werden (z. B. am Montag auf 6 Uhr morgens):
Eine manuelle Erstellung bietet sich dann an, wenn zum Zeitpunkt der automatischen Statistik-Erstellung die Tabelle keine repräsentativen Inhalte für Statistiken besitzt.
Ein Batch-Programm hat um 20 Uhr die Tabelle geleert, der Statistik-Erstell-Job um 22 Uhr ermittelt als Anzahl 0 Datensätze, um 2 Uhr morgens befüllt wiederum ein Batch-Job die Tabelle und um 10 Uhr erfolgt eine Query im Rahmen eines DataWareHouse-Systems. Der Oracle Optimizer ist hierbei nicht in der Lage, einen adäquaten Ausführungsplan zu erzeugen.
In einem solchen Fall ist es besser, den Statistik-Erstell-Job als Bestandteil des Ladeprozesses zu definieren. Der Aufwand für die Erstellung der Statistiken während des Ladeprozesses wird durch eine spürbare Laufzeitverbesserung des SQL-Statements (im DWH-Umfeld kann es sich um Stunden handeln) mehr als ausgeglichen.
Eine Alternative wäre auch, die Statistiken nach Beladung zu sperren oder zu löschen. Aufgrund der Möglichkeit des Optimizers, ein dynamisches Sampling bei Tabellen ohne Statistiken während der Laufzeit durchzuführen (init.ora-Parameter "optimizer_dynamic_sampling" Default=2) kann ein immer noch besserer Ausführungsplan als mit falschen Statistiken erzielt werden.
Für X$-Tabellen verwendet der Optimizer voreingestellte Statistikwerte, die nicht unbedingt ein Abbild der tatsächlichen Beladung darstellen. Da Dynamic Sampling nicht automatisch für diese Tabellen verwendet wird, sollten Statistiken folgendermaßen erzeugt werden:
Die Statistik-Erstellung für Fixed Objects sollte nach Datenbank-Upgrades oder nach Änderungen in der Datenbank-Konfiguration wiederholt werden.
Neben den Objekt-Statistiken benötigt der Oracle Optimizer Informationen über die Kapazität des Systems, auf dem die Datenbank läuft.
Bei der Ausführung der Query „select * from mqs.consulting order by mitarbeiter“ kommen im wesentlichen zwei Ausführungspfade in Betracht:
Wenn das System über schnelle CPUs und langsame Platten verfügt, ist der erste Ausführungspfad günstiger. Bei schnellen Platten und langsameren CPUs ist möglicherweise der zweite Pfad günstiger.
Damit sich die Datenbank einen Überblick über das System verschaffen kann, ist es empfehlenswert, mit folgender Prozedur Systemstatistiken zur Hauptverarbeitungszeit zu erstellen:
Die von Oracle im Intervall von 60 Minuten ermittelten Werte können anschließend der VIEW SYS.AUX_STATS$ entnommen werden.
Fazit
Das Vorhandensein von passenden Objekt-Statistiken ist die unabdingbare Voraussetzung für ein performantes Datenbanksystem und eine hohe Akzeptanz auf Anwenderseite.
Statistiken auf Fixed Tables und auf Systemressourcen verbessern den Durchsatz in der Datenbank, haben aber bei weitem nicht den Effekt wie die Objekt-Statistiken.
Detaillierte Informationen zu Statistiken erhalten Sie in den DB Tuning , SQL Tuning und Optimizer Schulungsangeboten der Muniqsoft GmbH.
Wer je Daten für eine Web-Applikation bereitstellen musste, kennt das Problem der Pagination. In der Regel holt das Frontend ja nur die Daten, die auf eine Seite passen, und erst wenn mehr angefordert werden, werden auch mehr geholt. Das stellt den Programmierer vor die Schwierigkeit, die Daten entprechend "mundgerecht" zu liefern. Entscheidend dabei ist in jedem Fall eine absolut eindeutige Sortier-Reihenfolge.
Ein klassischer von Tom Kyte u. a. hier Öffnet externen Link in neuem Fenster hier beschriebener Ansatz über ROWNUM sieht dann so aus:
Anmerkung: Für die folgenden Beispiele wurde eine Tabelle OBJECT_TAB als Kopie von ALL_OBJECTS erstellt.
Angewendet auf diese Tabelle sähe ein Select, der die Zeilen 11 bis 20 holt, z. B. so aus:
Der Ausführungsplan zeigt, dass der Optimizer hier mit Stopkeys arbeitet:
Anmerkung: Um Zeilenumbrüche in der Darstellung zu verhindern, wurden überflüssige Leerzeichen und Schema-Angaben aus dem Ausführungsplan entfernt.
Im PL/SQL-Umfeld würde eine entsprechende Prozedur - stark vereinfacht - z. B. so aussehen:
Da man jedoch gerade bei Suchmasken in der Regel mit dynamischen SQL arbeiten muss, ist das wohl etwas näher dran:
Das funktioniert zwar, ist aber nicht direkt intuitiv.
Mit Version 12c hat nun Oracle eine neue Klausel zur Begrenzung der Zeilen eingeführt, die die Syntax in solchen Fällen deutlich vereinfacht.
Angegeben werden können dabei:
Das obige Beispiel würde in 12c so aussehen:
Glaubt man dem Ausführungsplan, so ist diese Abfrage nicht nur wesentlich lesbarer, sondern auch noch performanter:
Anmerkung: Auch hier wurden überflüssige Leerzeichen und Schema-Angaben aus dem Ausführungsplan entfernt.
Eine Prozedur analog zu oben würde dann so aussehen:
Wesentlich lesbarer, oder?
Welche Möglichkeiten bietet die neue Klausel noch? Neben dem oben angegebenen <n> ROWS kann auch ein Prozentsatz mitgegeben werden mit <n> PERCENT ROWS. Das würde dann so aussehen:
Sollte die Sortierung nicht eindeutig sein (und auch nicht sein müssen), so kann man angeben, dass alle Datenätze mit ausgegeben werden sollen, die den gleichen Wert haben wie der zuletzt geholte. Dazu gibt man statt ONLY an WITH TIES. Der Effekt sei hier gezeigt an der allseits bekannten Tabelle SCOTT.EMP:
Diese neue Klausel ist prinzipell nicht abhängig von der ORDER BY-Klausel. Ihre vollen Möglichkeiten entfaltet sie aber nur hier.
Mehr zu diesem Thema erfahren Sie in unserer Schulung Oracle Neuerungen 12c, schauen Sie doch einfach vorbei :-)
Seit dem Erscheinen der Oracle Datenbank 12c wurde eine Reihe von Security Features, die bisher Bestandteil der Advanced-Security-Option (ASO) waren, als Feature für die Datenbank verfügbar gemacht. Dies gilt für die Enterprise Edition und auch für die Standard Edition. Siehe auch Oracle icensing Guide.
Auf der Serverseite unter UNIX $ORACLE_HOME/network/admin, oder unter Windows %ORACLE_HOME%\network\admin folgende Einträge in der sqlnet.ora vornehmen:
Die sqlnet.ora des/der Client/s wird nicht modifiziert.
Die Bedeutung der Werte im Einzelnen:
SQLNET.CRYPTO_CHECKSUM_TYPES_SERVER
mögliche Werte
SQLNET.CRYPTO_CHECKSUM_SERVER
SQLNET.CRYPTO_SEED
Der Wert sollte aus 10 bis 70 Buchstaben, Zahlen und Sonderzeichen bestehen. SQLNET.CRYPTO_SEED ist notwendig für die Checksummenprüfung und die Verschlüsselung. Als default wird der Wert "qwertyuiopasdfghjkl;zxcvbnm,.s1" verwendet.
SQLNET.ENCRYPTION_TYPES_SERVER
Die zur Verfügung stehenden Verschlüsselungs Algorythmen sind:
SQLNET.ENCRYPTION_SERVER
Der Test:
Das Funktionieren der SQL*Net Verschlüsselung lässt sich ganz einfach überprüfen. Dazu wird in der sqlnet.ora das Tracing aktiviert.
Serverseitig:
Clientseitig:
Die Tracefiles unverschlüsseltvom Server:
vom Client:
Die Tracefiles verschlüsseltvom Server:
Fazit:
Die SQL*Net Verschlüsselung ist einfach einzurichten und es entstehen keine zusätzliche Kosten. Performanceunterschiede zwischen verschlüsselter und unverschlüsselter Datenübertragung sind nicht bekannt.
Sollten Sie Interesse an weiteren Sicherheitsfunktionen zu Oracle Datenbanken haben, besuchen Sie doch unseren Kurs Datenbank Security.
Haben Sie schon einmal versucht Ihre Oracle Instanz zu starten und dabei feststellen müssen, dass Oracle keine Parameterdatei mehr findet? Gleichgültig, ob Sie eine binäre Datei, also ein SPFILE, oder eine ASCII-Datei verwenden, benötigt Oracle für den Startvorgang eine Datei, aus der die Basis-Parameter (Kontrolldateien, SGA-Parameter, UNDO-Verwaltung etc.) ausgelesen werden. Wird beim Start über SQL*Plus keine Parameterdatei gefunden und auch kein PFILE explizit angegeben, kommt es zu folgender Fehlermeldung:
Ein Starten ohne Parameterdatei ist offensichtlich nicht möglich. Jedoch gilt hier die Devise: nicht gleich aufgeben!
Hinweis
Bei den folgenden Szenarien wird grundsätzlich davon ausgegangen, dass das Backup des SPFILEs mittels RMAN erzeugt worden ist. Im Idealfall ist der RMAN-Konfigurationsparameter CONTROLFILE AUTOBACKUP auf ON gesetzt, wodurch automatische Backups vom Controlfile und SPFILE verfügbar sind.
Öffnen Sie nun den RMAN, melden Sie sich über diese Oberfläche an und probieren Sie den Startvorgang erneut.
Auch hier kommt es zur obigen Fehlermeldung, allerdings ist der RMAN in der Lage die Instanz mittels temporärer Dummy-Parameterdatei dennoch zu starten.
Oracle generiert dazu auch eine neue Alertdatei (unter ORACLE_BASE/diag/rdbms/dummy) in der folgende Initialisierungsparameter aufgelistet werden:
Wenn Sie erst einmal soweit gekommen sind, dann ist der Rest - das Neuerzeugen des SPFILEs aus dem RMAN Backup und ein erneutes Durchstarten - auch nicht mehr schwer. Dazu kommen wir allerdings etwas später.
Zunächst widmen wir uns aber dem eigentlichen Zweck dieses Tipps, nämlich den möglichen Problemen, die beim Startvorgang über den RMAN evtl. auftreten können.
Unter Windows 7 bzw. 2008 Server kann es notwendig sein, die Kommandozeile aus der heraus Sie den RMAN starten, mit dem Zusatz "Als Administrator ausführen" zu öffnen. Ansonsten erhalten Sie den Fehler:
Das zweite Problem stellt sich wesentlich dramatischer dar:
Wagt man nun einen Blick in die gerade neu erzeugte Alertdatei unter %ORACLE_BASE%\diag\rdbms\dummy, dann erkennt man eine Reihe von Speicherfehlern und abschließend den Absturz der Instanz. Hier ein Auszug aus der Alertdatei:
Läuft Ihre Datenbank unter Windows, muss an dieser Stelle sogar der Datenbankdienst OracleService <sid> neu gestartet werden, ansonsten ist ein weiteres Arbeiten nicht mehr möglich.
Tritt dieses Verhalten auf, dann sind Sie in einen dokumentierten Bug (# 9680987) für die Version 11.2.x hineingelaufen. Dabei sind die Dummy-Werte, die der RMAN zum Starten der Instanz verwenden möchte nicht ausreichend dimensioniert.
Als Workaround für dieses Problem setzen Sie vor dem RMAN-Aufruf einfach die Systemvariable ORA_RMAN_SGA_TARGET und starten dann erst über den RMAN Ihre Instanz.
Haben Sie es - trotz aller Widrigkeiten - geschafft Ihre Instanz ohne Parameterdatei in die NOMOUNT-Phase zu versetzen, dann fehlt jetzt nur noch das Zurückspielen des SPFILEs und das erneute Durchstarten, damit das gerade erzeugte SPFILE herangezogen werden kann. Bis zur Version 10.2 mussten Sie vor dem Restore des SPFILEs erst noch die DBID Ihrer Datenbank setzen, ab Version 11g ist dies optional.
Sie sehen, mit Hilfe des RMAN ist auch das Neuerzeugen eines SPFILEs keine Hexerei mehr und auch bei Auftreten eines der oben beschriebenen Probleme relativ einfach durchzuführen.
Ist die Parameterdatei nur logisch zerstört worden, aber physisch noch vorhanden, muss sie vor dem Starten mittels RMAN erst komplett entfernt werden.
Diese und weitere Tipps rund um den RMAN erhalten Sie in einem unserer RMAN oder Backup & Recovery Kurse. Schauen Sie sich einfach einmal auf unserer Schulungsseite um.
Die SQL*Plus Hilfe war bis zur Version 8.1 eigentlich recht hilfreich, da sie bei der Syntax von SQL und PL/SQL immer recht gut weitergeholfen hat. Leider wird dieser Bereich von Oracle nicht mehr gepflegt, es wurde nur noch die SQL*Plus Syntax in der Hilfe gelassen.
Es ist Zeit, hier etwas zu verbessern. Hinweis: Dies ist von Oracle nicht supported! und sollte deshalb nur auf Testdatenbanken verwendet werden.
Wenn die Hilfe-Tabelle noch nicht existiert, legen Sie diese bitte mit folgendem Skript an:
Dann schauen wir uns die Struktur der Tabelle einmal genauer an:
Die Topic-Spalte ist für den Text verantwortlich nach dem gesucht wird, die Info-Spalte gibt dann den Hilfetext zurück. Die SEQ-Spalte ist für mehrzeilige Texte gedacht. Sie muss pro Topic eindeutig sein.
Wenn wir in die Tabelle die Werte ('Muniqsoft-Training',1,'Schulung Tel.: 089 67909040') eintragen dann liefert der Befehl zurück:
Hinweis:Für einige Hilfetexte ist in den Spalten zu wenig Platz, deswegen vergrößern wir zwei Spalten. In der Version 12.1 hat das funktioniert. In älteren Versionen kann es zu Problemen kommen, dann lassen Sie den Schritt weg. Jedoch können Sie dann natürlich auch nicht so viel Text in die Spalten eintragen.
Zum warmwerden, tragen wir ein paar Texte ein (Ein bisschen Schleichwerbung muss schon sein :-) )
Und testen das mit:
Nun legen wir richtig los:
Wie wäre es mit allen undokumentierten Parametern mit Beschreibung (in zwei Zeilen wegen der Länge):
Aber es geht noch besser: Wenn wir dynamische Infos wie z. B. aus V$SESSION oder DBA_USER oder ... mit der Hilfe anzeigen wollen, dann verschieben Sie die Ursprungstabelle help in eine Tabelle help_tab und konsolidieren alle Informationen in einer View:
Das testen wir z. B. mit:
Weitere Ideen zu diesem Thema lernen Sie in unserem SQL*Plus Tageskurs. Sie können das Konzept natürlich selbst nach Belieben erweitern, z. B. SQL Area Befehle anhand der SQL_ID ausgeben oder alle Locks anzeigen. Wenn Sie weitere Punkte integriert haben, schicken Sie sie uns doch bitte, dann machen wir nochmal einen Bonus Track zu diesem Tipp.
Lange haben wir darauf gewartet, endlich ist sie da! Oracle 12c! Das "c" steht für Cloud.Wir wollen in dieser Reihe einige neue Features vorstellen, die wir natürlich auch in unserem Oracle 12c Kurs ausführlich besprechen.
Oracle 12c: Identity SpaltenDer SQL Server kann es schon seit einiger Zeit, Oracle nun auch ab Version 12c.Eine Primärschlüsselspalte kann automatisch mit einem Wert gefüllt werden. Einfachster Fall, Sequenz soll bei 1 starten, Schrittweite 1:
Oder etwas aufwendiger mit Startwert 100 und Schrittweite 10 (aber ohne Primärschlüssel):
Möchten Sie eine bestehende Identity löschen ?
Auch ein nachträgliches Setzen der Identity ist möglich, mit neuer Spalte:
Wenn ein bestehender Sequenzwert um 100 erhöht werden soll, kann man die Identity auf der Spalte löschen und einfach neu setzen.
Sie können pro Tabelle nur eine Identity Spalte festlegen. Wird die Identity Klausel verwendet, dann muss der Datentyp in der Spaltendefinition numerisch sein. Ein benutzerdefinierter Datentyp kann nicht spezifiziert werden.
Sie müssen nicht zwingend eine Primärschlüsselspalte für die Identity verwenden.Das Setzen eines Defaultwertes in der Spaltendefinition ist bei der Verwendung der Identity Klausel nicht erlaubt. Wird die Identity Klausel verwendet, so wird automatisch ein NOT NULL Constraint auf die Spalte gesetzt.
Wie funktionierts ?Oracle legt eine Sequenz im Schema der Tabelle an (z. B. mit Namen ISEQ$$_12345 und als Default mit Cache=20). Einen Insert-Trigger haben wir jedoch nicht entdeckt.
Sie können feststellen, welche Tabelle Identity Spalten verwendet:
Oder wenn Sie wissen wollen, welche Spalte vom Typ Identity ist:
Ausführliche Optionssyntax:
Komplexes Beispiel:
>100 weitere neue Funktionen der Oracle 12c Version lernen Sie in unserem Oracle 12c Neuerungen Kurs kennen.
An einer Tabelle hängen viele schöne Objekte, die man aber auf den ersten Blick gar nicht sieht.
So gibt es zum Beispiel:
Sequenzen stehen eigentlich nicht mit einer Tabelle in direktem Zusammenhang. Wenn sie aber in einem Trigger referenziert werden, der auf der Tabelle basiert, kann man (meistens) davon ausgehen, dass sie zum Füllen der Primärschlüsselspalte verwendet werden. Sequenzen, die durch die Applikation direkt aufgerufen werden, kann man leider keiner Tabelle zuordnen.
Der folgende Select zeigt Ihnen eine Zusammenfassung aller Objekte, die mit einer gegebenen Tabelle in Verbindung stehen.In der ersten Zeile (WITH t ...) gibt man einfach den Benutzernamen und den Tabellennamen ein.Hier wurde die Tabelle emp des Benutzers Scott verwendet:
Wenn Sie schon die Oracle Version 23c besitzen können Sie auch noch Annotations einer Tabelle anzeigen. Dann entfernen Sie bitte im obigen Select das letzte “;” und hängen folgenden Teil dran:
UNION ALL SELECT 'Annotations',a.column_name, a.annotation_name, a.annotation_value FROM all_annotations_usage a,t WHERE a.owner=t.tab_owner AND a.object_name = t.tab_name ORDER BY column_name NULLS FIRST,domain_name NULLS FIRST,annotation_name;
Und weil wir gerade warm gelaufen sind, wäre es doch praktisch, die Statements für alle Objekte zu erzeugen, nur für den Fall, dass man mal ein Objekt verliert oder neu erstellen möchte.Auch dafür kann man einen SELECT schreiben.
Zunächst sorgen wir dafür, dass jeder der erzeugten DDL-Befehle mit einem Semikolon abgeschlossen und die Storage-Klausel nicht mit ausgegeben wird...
... und benutzen das Package DBMS_METADATA für die Erstellung der nötigen SQL-Befehle:
Anmerkungen:Man kann leider nicht in jedem Fall auf die ALL_... Variante der Data Dictionary Views zurückzugreifen, weil es z.B. keine ALL_OBJ_AUDIT_OPTS View gibt. Wenn man keine DBA Rechte hat, ersetzt man einfach den Bezug (DBA_OBJ_AUDIT_OPTS) durch USER_OBJ_AUDIT_OPTS und wirft den Filter "AND oao.owner=s.orig_tab_owner" weg.Die Filter "AND rownum=1" sind nicht zum Spaß da. Da das Package dbms_metadata abstürzt, wenn man nicht vorhandene Audit-Informationen oder Rechte eines Objekts abfragen will, muss man erst mal prüfen, ob es da etwas gibt. Mit einer Zeile bekommt man dann aber alle Rechte/Audit-Einstellungen zurück :-)
Weitere Möglichkeiten, diese Funktionen auch in einer Online Reorg einzusetzen, lernen Sie bei uns im Reorg- und Wartungskurs sowie im Standard Edition Kurs kennen. Wir freuen uns auf Ihr Kommen!!
Sind Sie als DBA Ihrer Oracle Datenbank auch für das Backup und Recovery zuständig? Dann standen Sie vielleicht schon einmal vor dem Problem, Ihre Datenbank aufgrund von Benutzer- oder Dateifehlern zurücksetzen zu müssen. Passiert dies einmal, ist das zwar sehr ärgerlich, aber in Verbindung mit dem RMAN noch sehr unkompliziert. Kommen Ihre Entwickler aber häufiger mit dem Wunsch auf Sie zu, die (Entwickler- oder Test-) Datenbank doch noch weiter zurückzusetzen als beim letzten Mal oder den letzten OPEN RESETLOGS ganz ungeschehen zu machen, dann wird das Ganze schon trickreicher und komplizierter.
Im folgenden Artikel werden Ihnen einige mögliche Szenarien vorgestellt, mit denen Sie in diesem Zusammenhang evtl. einmal konfrontiert werden.Eines noch vorneweg: Diese Szenarien wurden nicht extra für diesen Tipp erfunden und ersponnen, sondern es handelt sich dabei um reale Probleme, mit denen Kunden im Laufe der letzten zehn Jahre Schulungs- und Supporttätigkeit auf uns zugekommen sind.
Zur Ausgangssituation: Die Beispiel-Datenbank wird regelmäßig ONLINE mittels RMAN im NOCATALOG-Modus gesichert. Zielverzeichnis ist die Fast (Flash) Recovery Area, kurz FRA.
Um 08:30 kommt einer Ihrer Entwickler mit der Bitte zu Ihnen, den gestrigen Löschvorgang eines Applikationsschemas (HR) rückgängig zu machen. Dazu setzen Sie die Datenbank auf 15:25 des Vortags zurück.
Damit ist das komplette Schema HR wiederhergestellt. Allerdings sind (verständlicherweise) sämtliche Änderungen, die seit 15:25 durchgeführt worden sind, verloren.
Gegen 09:00 kommt der selbe Entwickler und benötigt in "seiner" Datenbank nun einen Stand von 10:15, der aber zwei Tage zurückliegt.
Der erste Lösungsansatz, den Sie analog zum Szenario 1 versuchen, wird mit folgendem Fehler quittiert:
Das Problem liegt darin, dass der gewünschte Zeitpunkt aus einer alten Inkarnation stammt, in die Oracle beim RESTORE/RECOVER nicht automatisch wechseln kann. Die Auflistung der einzelnen Inkarnationen stellt sich wie folgt dar:
Die aktuelle Inkarnation ist die Nummer 4. Damit der Recovervorgang erfolgreich durchgeführt werden kann, muss zuerst auf die Inkarnation Nummer 3 zurückgesetzt werden. Somit ergibt sich als korrekte Lösung folgendes Vorgehen:
Nachdem Sie auch das zweite Szenario erfolgreich beendet haben und dem Entwickler "seine" Datenbank auf den gewünschten Stand zurückgesetzt haben, kommt um 09:45 der Chef der Entwickler, dessen Arbeit der vergangenen zwei Tage Sie gerade zunichte gemacht haben, und verlangt umgehend die Wiederherstellung der Datenbank vom heutigen Stand 08:30.
Bevor Sie jetzt in Hektik ausbrechen, nehmen Sie zunächst einen (Data Pump) Export der aktuellen Datenbank bzw. einzelner Schemata vor. Damit können Sie am Schluss (hoffentlich) alle Entwickler zufriedenstellen.
Nun geht es darum, alle Spuren der OPEN RESETLOGS Vorgänge zu verwischen. Dazu wird ein altes Controlfile eingespielt, das vor dem ersten RESETLOGS von 08:45 erstellt worden sein muss. Gehen Sie in das Verzeichnis, in das die Backupsets der Controlfiles geschrieben werden (idealerweise das AUTOBACKUP Verzeichnis in der FRA) und verschieben Sie alle aktuelleren Backups in ein temporäres Verzeichnis. Je nach Version von Oracle, müssen Sie evtl. vor dem RESTORE CONTROLFILE noch die DBID setzen (falls notwendig, werden Sie aber dazu aufgefordert).
Spätestens jetzt müssen Sie die restlichen Backupsets der Datendateien und der Archivelogs verschieben. Wenn es noch Original-Archivelogs aus den neuen Inkarnationen gibt, müssen auch diese entfernt werden. Wenn Sie daraufhin den RESTORE DATABASE Befehl anstoßen, werden nur die Backups aus der ursprünglichen Inkarnation katalogisiert. Die letzten beiden Inkarnationen sind damit nicht mehr existent.
Die Parallelisierung von größeren DELETE- und UPDATE-Aktionen bietet diverse Vorteile:
Wenn man selber prozedurale Lösungen zum parallelen Löschen oder Aktualisieren großer Datensatzmengen erstellen will, wird das allerdings schnell mühsam, weil man erst einmal sicherstellen muss, dass die Pakete so aufgeteilt werden, dass sich die einzelnen Transaktionen nicht gegenseitig behindern.Ab der Oracle Version 11 Release 2 gibt es eine Oracle-eigene Lösung für die Parallelisierung von DML-Aktionen über den Scheduler, die den Anwendern sehr viel Arbeit abnehmen kann, das Package DBMS_PARALLEL_EXECUTE.In diesem Fall werden die Tabellen über einen DBMS_SCHEDULER-Prozess automatisch in Teilbereiche, sog. Chunks, unterteilt (die aber nichts mit den Chunks bei der Speicherung von LOBs zu tun haben). Auf diese Abschnitte werden die DML-Befehle parallel abgesetzt. Ein COMMIT erfolgt nach jeder Fertigstellung des DML-Befehls auf dem jeweiligen Tabellenbereich. Dadurch werden die Undo-Segmente weniger stark belastet.Um das Fehlerlogging und automatische Wiederholungen im Fehlerfall kümmert sich ebenfalls der Scheduler.Die einzige Voraussetzung für die Nutzung ist das CREATE JOB-Recht. Das Package an sich ist an Public gegrantet. Im Gegensatz zu den meisten anderen Optionen, die mit Parallelisierung zu tun haben, ist die Nutzung des Packages nicht auf die Enterprise Edition beschränkt!!Das Package besteht aus folgenden Prozeduren, die alle einen Commit beinhalten.
Die Funktion TASK_STATUS kann zum Monitoren und zur Fehlerbehandlung genutzt werden.
Probieren's wir mal aus. Für den ersten Test nehmen wir Tom Kytes bewährte Tabelle Initiates file downloadbig_tab mit 2 Millionen Datensätzen. Weil wir später die Session_ids bei der parallelen Ausführung ermitteln wollen, benennen wir die data_object_id-Spalte in session_id um.
Zunächst braucht Scott das Create Job-Recht:
Jetzt kann Scott einen Task erstellen. Der Taskname ist einfach ein VARCHAR2-Parameter. Er muss nicht den Regeln für Oracle-Bezeichner entsprechen:
Ob die Erstellung geklappt hat, kann man über die View USER_PARALLEL_EXECUTE_TASKS herausfinden:
Falls einem grad kein passender Name einfällt, kann man die Funktion GENERATE_TASK_NAME verwenden, die eine interne Sequenz hochzählt:
Der nächste Schritt ist die Unterteilung der Tabelle. Wenn der Parameter by_row auf TRUE gesetzt wird, bezieht sich die chunk_size auf die Anzahl der Zeilen, wenn er auf FALSE steht, auf die Anzahl der Blöcke.Optimale Werte für die chunk_size muss man selber ermitteln. Je kleiner die chunk_size, desto schneller sind die Tabellenabschnitte wieder frei von Sperren:
Genauere Informationen über die einzelnen Abschnitte liefert die View USER_PARALLEL_EXECUTE_CHUNKS:
Jetzt folgt die eigentliche Ausführung:In diesem Beispiel werden 10 parallele Prozesse (Scheduler-Jobs) gestartet, die sich jeweils einen der nicht zugeordneten (unassigned) Abschnitte vornehmen, die über den Parameter sql_stmt vorgegebene DML-Anweisung durchführen, festschreiben und zum nächsten freien Chunk übergehen. Wenn man z. B. nur 4 Prozessoren hat, laufen die Jobs natürlich teilweise seriell.Der Quotation-Operator (q'[...]') erlaubt die Schreibweise ohne Maskierung der inneren Hochkommata:
Die Bindvariablen :start_id and :end_id beziehen sich auf die erste bzw. letzte Rowid jedes Chunks.Der Eintrag der Session_id über die Sys_constext-Funktion ermöglicht auch nachträglich, festzustellen, welcher Anteil der Zeilen in welcher der parallelen Sessions erledigt wurde:
Ob alles glatt gegangen ist, erfährt man über die Data Dictionary-Views:
Aufschlussreich ist auch die Scheduler-DD-View user_scheduler_job_run_details. Hierfür muss man nur das Job-Präfix aus der View user_parallel_execute_tasks für die Job-Namen einsetzen:
Nach der erfolgreichen Ausführung kann man den Task löschen:
Was macht man, wenn bei der Prozessierung Fehler auftreten? Wir bauen ein paar Fallen in die Tabelle ein. Die Spalte object_type ist vom Datentyp VARCHAR2(19). Während des Updates wird der Wert mit einem Sternchen konkateniert, also muss ich nur ein paar Einträge verlängern, so dass es während der DML-Aktion kracht:
In der PL/SQL Packages and Types Reference findet sich ein Beispiel für die Ausführung der Prozedur incl. Fehlerbehandlung. Statt RUN_TASK wird hier die Prozedur GET_ROWID_CHUNK eingesetzt:
Sie betreiben Ihre Oracle Datenbank unter Windows und Ihnen geht der lokale Speicherplatz allmählich aus? Trotzdem soll natürlich weiterhin archiviert werden und auf die regelmäßigen RMAN-Backups wollen Sie verständlicherweise auch nicht verzichten. Haben Sie sich nicht schon häufiger gefragt, ob es keine Möglichkeit gibt, die Archivelogs und die RMAN Backupsets direkt auf einem Remote-Rechner zu erzeugen? Im vorliegenden Tipp erfahren Sie, wie Sie genau dies erreichen können.
Die Frage nach Remote-Archivierung (ohne eine Standby Datenbank aufbauen zu müssen) ist bestimmt nicht neu und eigentlich auch schon seit Längerem realisierbar gewesen. Der Versuch der Umsetzung führte allerdings oftmals zu größeren Frustrationserlebnissen. Stattdessen wurde der verfügbare Speicherplatz einfach um eine lokale Platte erweitert.
Hier nun die Schritte, die für eine (hoffentlich) erfolgreiche Einrichtung notwendig sind.
Da es in aller Regel an den Berechtigungen scheitert, muss auf Zielseite zunächst ein Administrator-Account eingerichtet werden. Dafür ist der gleiche Name und das gleiche Passwort wie auf Quellseite zu vergeben. In unserem Beispiel ist das der Benutzer "schulung" mit einem (natürlich streng geheimen) Passwort.
Damit remote archiviert werden kann, benötigen Sie eine Freigabe auf dem Remote-Rechner. Geben Sie z.B. das Verzeichnis C:\Temp frei, so dass der Benutzer "schulung" lesend und schreibend darauf zugreifen kann. Als Zielverzeichnis für die archivierten Redo Logfiles und evtl. die RMAN Backupsets wird innerhalb von C:\Temp noch das Verzeichnis "FRA" angelegt.
Standardmäßig laufen alle Oracle Dienste unter dem "Local System" Account. Stellen Sie diese auf den lokalen Administrator "schulung" um. Dazu gehen Sie in den Eigenschaften des Dienstes auf die Registerkarte "Anmelden" und wählen "Dieses Konto" für die Anmeldung aus. Tragen Sie nun den Benutzer "schulung" und sein Kennwort ein.
Anschließend erhalten Sie die folgenden Windows-Meldungen
Danach starten Sie den Dienst neu. Achten Sie darauf, dass alle gestarteten Oracle Dienste unter dem selben Account laufen. Hier sind das die Dienste "OracleService<sid>" und "Oracle<Home>TNSListener".
Im letzten Schritt definieren Sie Ihr Remote-Verzeichis als neues Zielverzeichnis für die Archivelogs und/oder Backupsets. Bei der Pfadangabe sind allerdings nur UNC-Pfade erlaubt. Die Verwendung von Laufwerksbuchstaben wird bei Remote-Verzeichnissen nicht unterstützt.
Das Zielverzeichnis kann sowohl über die Flash bzw. Fast Recovery Area gesetzt werden, als auch direkt über einen der log_archive_dest<n> Parameter. Zulässig sind folgende Beispiele:
Falls Sie die Fast Recovery Area auch für Ihre RMAN Backups verwenden, lassen sich somit auch die Backupsets direkt auf einem Remote-Server erzeugen, ohne dass Sie irgendetwas an Ihren Backup-Skripten verändern müssen.
Nicht zulässig ist folgende Angabe (trotz eingerichteter Netzlaufwerksverbindung Z:)
Sind die oben beschriebenen Schritte 1-3 vorgenommen worden, so lassen sich ebenfalls Control- und Online Redo Log-Dateien sowie das SPFILE remote verwenden.
Soll das SPFILE remote genutzt werden, verschieben Sie es in das Remote-Verzeichnis und erstellen Sie eine INIT<sid>.ORA Datei mit folgendem Inhalt:
Auch Datendateien lassen sich auf diese Weise remote anlegen, allerdings kam es bei unseren Tests zu wiederkehrenden Fehlermeldungen in der Alertdatei.
Dies hatte zwar keine (merkbare) Auswirkung auf die Verfügbarkeit der Datendatei und deren Inhalt, aber besonders beruhigend ist diese Fehlermeldung auch nicht.
Das Ablegen von Oracle Dateien auf einem Remote-Rechner ist also keine Hexerei und mit wenigen Schritten durchführbar.
Allerdings ist zu beachten, dass Sie in all diesen Fällen auf eine permanent bestehende (und auch schnelle) Netzwerkverbindung angewiesen sind, ansonsten hängt Ihr Datenbanksystem oder stürzt im schlimmsten Fall sogar ab.
Viele weitere interessante Informationen rund um die Administration von Oracle Datenbanken erhalten Sie in unseren DBA Kursen. Schauen Sie doch mal vorbei.
Der Export von Tabellen als csv-Files ist immer wieder ein Thema in unseren PL/SQL- und Packages-Kursen, weil die meisten gerne mit Excel arbeiten. Deshalb gebe ich unseren Teilnehmern immer eine einfache Prozedur mit, über die man Inhalte beliebiger Tabellen (solange sie keine LOB-Spalten oder ähnliches enthalten) mittels UTL_FILE als semikolon-separierte Ascii-File exportieren kann. Der Einsatz von UTL_FILE ist nicht der schnellste Weg, aber man kann diese Prozeduren sehr gut in Datenbank-Jobs einbinden oder für andere PL/SQL-Programme verwenden.
Bei Tom Kyte findet man übrigens eine schöne Übersicht seiner diversen Export-Utilities. Für seine PL/SQL-Funktion dump_csv verwendet er DBMS_SQL
Das Problem ist allerdings: Mit den üblichen Beispieltabellen wie scott.emp oder all_objects klappt das alles natürlich prima, aber wie sieht's denn aus, wenn man "historisch gewachsene" Tabellen mit fast 100 oder mehr Spalten vor sich hat, in denen wegen der Verwendung von CHAR-Datentypen u. U. viel heiße Luft gespeichert ist? Deshalb wollte ich mal ausprobieren, wie man einserseits die kleine Prozedur ausbauen müßte, um solche Problemfälle in den Griff zu kriegen und welche Möglichkeiten es gibt, das Ganze schneller zu machen.
Von Adrian Billington stammt ein sehr lesenswerter Artikel von 2008: PL/SQL-File-IO über verschiedene Ansätze, die einfache Ausgabe über UTL_FILE zu beschleunigen und Performance-Vergleiche zwischen dem Einsatz von UTL_FILE auf der einen und der Kombination von DBMS_LOB und DBMX_XSLPROCESSOR auf der anderen Seite. Seine Codebeispiele für UTL_FILE habe ich leicht abgewandelt, in meine alte Exportprozedur eingebaut und mit verschiedenen Tabellen getestet.
Die Erstellung der Spaltenlisten wird in eine Funktion ausgelagert. Die TRIM-Funktion macht beim späteren Export die CHAR- und VARCHAR2-Spalten-Inhalte "schlanker", indem sie Leerzeichen von beiden Seiten löscht.
Diese Prozedur exportiert den Inhalt einer Tabelle als csv-File (mit der Angabe von Datum und Uhrzeit). Das Directory muss natürlich existieren und der Ersteller der Prozedur muss Lese- und Schreibrechte darauf haben.
In der folgenden Prozedur habe ich Adrian Billingtons Idee zur Zwischenspeicherung der Zeilen in einer 32KB-VARCHAR2-Variable verwendet. Erst wenn der Puffer voll ist, wird die Zeile geschrieben. Vor allem für größere Tabellen macht das einen Unterschied.
Und jetzt Billingtons Turboversion mit Parallel-Antrieb (etwas vereinfacht). Die parallele Ausgabe funktioniert nur mit einer Table Function und ist deshalb etwas komplexer. Zudem ist die Parallelisierung nur bei der Enterprise-Edition möglich.
Statt mit einem Cursor durch die Ergebnismenge zu laufen, wird hier eine nested Table verwendet, die in Portionen von je 100 Zeilen befüllt wird (Dies allein bringt noch keinen Geschwindigkeitsgewinn, da auch bei der Ref Cursor-Version im Hintergrund ein Bulk Collect von je 100 Zeilen durchgeführt wird). Diese 100 Zeilen werden dann über die Puffermethode ins File geschrieben, dann holt sich die PL/SQL Engine die nächsten 100.Nach dem Schließen des Files wird als Dummy ein Sequenzwert über PIPE ROW ausgegeben, damit die Funktion einen Rückgabewert hat.
INFO
Seit APEX Version 5.1 können ja nun zusätzliche Standard-Prüfungen für die Items durchgeführt werden. Diese sind:
Wenn das aber alles nicht passt, können wir uns eine eigene Validation schreiben:
DECLAREstmt VARCHAR2(32000);v_sqlerrm varchar2(32000);BEGINFOR c IN (SELECT PAGE_ID, PAGE_NAME, ITEM_NAMEFROM APEX_APPLICATION_PAGE_ITEMSWHERE application_id=:APP_ID and page_id=:APP_PAGE_ID ) LOOP stmt:=q'!BEGIN IF instr(v('!'||c.item_name||q'!'),'<')>0 OR instr(v('!'||c.item_name||q'!'),'>')>0 OR instr(v('!'||c.item_name||q'!'),'^')>0 OR instr(v('!'||c.item_name||q'!'),'&')>0 OR instr(v('!'||c.item_name||q'!'),'"')>0 OR instr(v('!'||c.item_name||q'!'),chr(39))>0 THEN RAISE_APPLICATION_ERROR(-20500,'Ungültige Zeichen verwendet (^<>&")'); END IF; EXCEPTION WHEN OTHERS THEN IF sqlcode=-20500 then raise; end if; END; !';commit; EXECUTE IMMEDIATE stmt;
END LOOP; RETURN true;EXCEPTION WHEN OTHERS THEN v_sqlerrm:=sqlerrm; RETURN false;END;
Wenn jetzt jemand in irgendein Item eines der Zeichen <>'" &^ einträgt, wird diese Eingabe abgewiesen.
Es ist wohl eines der best gehütesten Geheimnisse, dass defekte Indizes in der Tabelle dba_objects in der Spalte weiterhin mit dem Status VALID stehen.Wenn man also festellen möchte, welche Indizes defekt sind, muss man in DBA_INDEXES bzw. DBA_PART_INDEXES nachsehen.Das nachfolgende Skript macht einen Rebuild auf alle defekten Indizes, ohne dass die Ausgabe zuerst gespoolt werden muss.
In diesem Tipp geht es um die Migration einer Non-Container Datenbank in die Container Architektur. Dabei soll auch gleichzeitig ein Upgrade auf die Version 12.2.0.1 erfolgen.Notwendigkeit des UmstiegsSeitdem im März 2013 die Version 12c erschienen ist, wird verstärkt über das zentrale neue Feature "Pluggable Database"diskutiert. Für die Einen endlich die Möglichkeit, ihre zahlreichen, kleinen (ähnlich gestrickten) Datenbanksysteme in einemzentralen DBMS zu konsolidieren und sich damit die Verwaltung zu vereinfachen, für die Anderen aus den verschiedenstenGründen nicht umsetzbar. Nicht zuletzt wegen der anfallenden Lizenzkosten für die Multitenant Option.Aber egal, wie sehr man diese neue Architektur auch ablehnt, wer Oracle weiterhin produktiv einsetzen und dabei auch Support"genießen" möchte, der kommt um die Migration auf die Container-Architektur nicht herum. Der Oracle Premier Support für 12.1.0.2ist (derzeit) bis Mitte 2019 und für 12.2.0.1 bis Mitte 2022 festgelegt worden. Danach wird laut Oracle Dokumentation (vermutlich)nur noch die neue Architektur supportet. Hier ein Auszug aus der Doku dazu:
Also wollen wir uns in diesem Monatstipp einmal ansehen, wie der eigentliche Migrations- und Upgrade-Vorgang aussehenkönnte. An der Stelle sei darauf hingewiesen, dass es verschiedene Alternativen gibt, um eine Migration von Non-CDB in CDBdurchzuführen, auf die hier nicht ganzheitlich eingegangen wird.Folgende Vorbereitungen müssen aber für alle Varianten getroffen werden:Die Binaries der Zielversion (12.2.0.1) sind bereits in einem neuen ORACLE_HOME installiert und eine neue (Ziel-)Datenbank (hiermit Namen O122CDB) wurde als Container-DB angelegt.Aber Achtung: Sobald Sie mehr als eine Pluggable Database innerhalb einer CDB installiert haben, müssen Sie die Multitenant-Lizenz erwerben. Falls dies nicht gewünscht ist, muss die CDB zunächst ohne Pluggable Database erzeugt werden. Dort hineinwird in den folgenden Schritten die Non-Container Quell-DB (o12c der Version 12.1.0.2) als PDB (pdb_o12c der Version 12.2.0.1)eingehängt.Die Empfehlung von Oracle, vor dem Upgrade den neuesten Bundle Patch (BP) oder PSU einzuspielen ignorieren wir zunächsteinmal, was sich allerdings sehr bald rächen soll ...Preupgrade PrüfungFür die Vorabprüfung eines Upgrades auf 12.2 gibt es ein neues Skript (PREUPGRADE.JAR). Dieses wird aus dem (alten)ORACLE_HOME heraus aufgerufen:
$ cd $ORACLE_HOME_<old>/jdk/bin
$ ./java -jar $ORACLE_HOME_<new>/rdbms/admin/preupgrade.jar
Im Idealfall sieht die Rückmeldung folgendermaßen aus:Preupgrade generated files:
/u01/app/oracle/cfgtoollogs/o12c/preupgrade/preupgrade.log
/u01/app/oracle/cfgtoollogs/o12c/preupgrade/preupgrade_fixups.sql
/u01/app/oracle/cfgtoollogs/o12c/preupgrade/postupgrade_fixups.sql
Falls bei der Durchführung Probleme auftreten, sollten die OS-Variablen ORACLE_HOME, PATH, PERL und PERL5LIB überprüftwerden.Durchführung des Upgrades und FehlerbehandlungIm Internet findet man etliche Anleitungen für das Upgrade, allerdings habe ich gemerkt, dass keine davon zusammenfassendalle Probleme behandelt, in die ich gelaufen bin, geschweige denn Lösungen dafür anbietet. Der folgende Tipp bietet hoffentlicheine hilfreiche Liste der möglichen Schritte und Hindernisse, erhebt jedoch ebenfalls keinen Anspruch auf Darstellung allermöglichen Fehler.Als Grundlage für den Upgrade, soll an dieser Stelle eine Variante gewählt werden, die zwar in der Doku enthalten, aber nachmeiner Erkenntnis noch nicht allzu weit verbreitet ist: (siehe Mike Dietrich: Öffnet externen Link in neuem Fensterhttps://mikedietrichde.com/2015/05/18/create-a-pdb-directly-from-a-stand-alone-database/ )Das remote Klonen einer Non-CDB über die NON$CDB Option mit Database Link.Dazu melden Sie sich am Root-Container der Ziel-Datenbank an und erzeugen einen Database Link zur Quell-Datenbank. AchtenSie auf den korrekten Eintrag in der TNSNAMES.ORA.Der Benutzer, mit dem die Verbindung über den DB-Link zur Quell-DB vorgenommen wird, benötigt das CREATE PLUGGABLEDATABASE Recht.
SQL> conn / as sysdba
SQL> CREATE DATABASE LINK o12c CONNECT TO system
IDENTIFIED BY <pwd> using 'o12c';
Nun der erste Versuch des Klonvorgangs:
$ mkdir /u01/app/oracle/oradata/o122cdb/pdb_o12c
SQL> CREATE PLUGGABLE DATABASE pdb_o12c FROM NON$CDB@o12c
file_name_convert=('/u01/app/oracle/oradata/o12c',
'/u01/app/oracle/oradata/o122cdb/pdb_o12c');
/*
CREATE PLUGGABLE DATABASE pdb_o12c FROM NON$CDB@o12c ...
*
ERROR at line 1:
ORA-17628: Oracle error 17630 returned by remote Oracle server
ORA-17630: Mismatch in the remote file protocol version client server
*/
Die Internetsuche ergab einen Bug, der durch das Einspielen des Patches 18633374 auf der Quellseite behoben wird (bitteReadme dazu lesen).
…
$ cd /tmp/18633374
$ opatch apply
## CODE ##
Danach der zweite Versuch:
ORA-00600: internal error code, arguments: [25029], [3], [3], [2], [], [], [], [], [], [], [], []
Dieser Fehler erfordert das Einspielen des aktuellen BP auf der Zielseite. In diesem Fall wird der Patch 27105253 im neuenORACLE_HOME eingespielt (Achtung Readme dazu).
$ cd /tmp/27105253
SQL> startup
SQL> ALTER PLUGGABLE DATABASE ALL OPEN;
$ cd $ORACLE_HOME/OPatch
$ ./datapatch -verbose
Und der dritte Versuch:
ORA-65353: The undo tablespace is missing from the XML metadata file.
Das Problem ist in diesem Fall der in 12.2 standardmäßig eingestellte LOCAL UNDO Modus. Der UNDO-Tablespace aus der Quell-DB kommt nicht mit, wird aber im Ziel erwartet. Also wird temporär LOCAL UNDO in der Ziel-DB auf FALSE gesetzt.
SQL> shutdown immediate
SQL> startup upgrade
SQL> ALTER DATABASE LOCAL UNDO OFF;
Aber jetzt, der vierte Versuch - na geht doch:
-- Pluggable database created.
In jedem Fall sollte man sich die PDB_PLUG_IN_VIOLATIONS View ansehen, um über WARNINGs und ERRORs informiert zuwerden.
SQL> col message for a200
col action for a150
col cause for a20
col time for a30
col name for a10
SQL> SELECT time, name, cause, type, message, status, action
FROM pdb_plug_in_violations;
...
VSN not match
ERROR
PDB's version does not match CDB's version: PDB's version 12.1.0.2.0. CDB's version 12.2.0.1.0.
PENDING
Either upgrade the PDB or reload the components in the PDB.
Non-CDB to PDB
WARNING
PDB plugged in is a non-CDB, requires noncdb_to_pdb.sql be run.
Run noncdb_to_pdb.sql.
Also muss die Pluggable Database PDB_O12C zunächst upgegradet werden. Dies erfolgt über den Aufruf des Perl-SkriptsCATCTL.PL
SQL> ALTER SESSION SET CONTAINER=pdb_o12c;
SQL> ALTER PLUGGABLE DATABASE pdb_o12c OPEN UPGRADE;
$ export ORACLE_HOME=/u01/app/oracle/product/12.2.0.1/dbhome_1
$ export ORACLE_SID=o122cdb
$ export PERL=$ORACLE_HOME/perl/bin
$ export PERL5LIB=$ORACLE_HOME/rdbms/admin
$ export PATH=$ORACLE_HOME/bin:$PERL:$PATH
$ cd $ORACLE_HOME/rdbms/admin
$ $ORACLE_HOME/perl/bin/perl catctl.pl -c 'PDB_O12C' catupgrd.sql
Argument list for [catctl.pl]
Run in c = PDB_O12C
catctl.pl VERSION: [12.2.0.1.0]
STATUS: [production]
BUILD: [RDBMS_12.2.0.1.0_LINUX.X64_170125]
/u01/app/oracle/product/12.2.0.1/dbhome_1/rdbms/admin/orahome =
[/u01/app/oracle/product/12.2.0.1/dbhome_1]
/u01/app/oracle/product/12.2.0.1/dbhome_1/bin/orabasehome =
catctlGetOrabase = [/u01/app/oracle/product/12.2.0.1/dbhome_1]
Analyzing file /u01/app/oracle/product/12.2.0.1/dbhome_1/rdbms/admin/catupgrd.sql
***************** Post Upgrade *****************
°Serial Phase #:112 [PDB_O12C] Files:1 Time: 55s
**************** Summary report ****************
Serial Phase #:113 [PDB_O12C] Files:1 Time: 1s
Serial Phase #:114 [PDB_O12C] Files:1 Time: 25s
Serial Phase #:115 [PDB_O12C] Files:1 Time: 0s
------------------------------------------------------
Phases [0-115] End Time:[2018_01_30 11:33:48]
Container Lists Inclusion:[PDB_O12C] Exclusion:[NONE]
Grand Total Time: 1620s [PDB_O12C]
Da sich die neue PDB im Modus RESTRICTED befindet, muss anschließend das Skript NONCDB_TO_PDB.SQL aufgerufen werden
SQL> ALTER SESSION SET container=pdb_o12c;
SQL> @?/rdbms/admin/noncdb_to_pdb.sql
Falls beim erneuten Versuch die PDB zu öffnen eine Warnung kommt
Warning: PDB altered with errors.
Pluggable Database opened.
sollte folgendermaßen vorgegangen werden:
SQL> ALTER SESSION SET CONTAINER=CDB$ROOT;
SQL> ALTER PLUGGABLE DATABASE pdb_o12c CLOSE;
SQL> ALTER PLUGGABLE DATABASE pdb_o12c OPEN RESTRICTED;
SQL> exec dbms_pdb.sync_pdb();
SQL> ALTER PLUGGABLE DATABASE pdb_o12c OPEN;
Zu überprüfen ist, ob der STATUS bei allen Meldungen von PENDING auf RESOLVED geändert wurde. Falls nicht, gibt die SpalteACTION Auskunft darüber, was zu tun ist. Nun sollte sich die PDB (ohne Probleme, Warnungen oder Fehler) öffnen lassen.Tipp: Überprüfen Sie ebenfalls die ungültigen Objekte und, falls welche vorhanden, versuchen Sie diese zu rekompilieren.
SQL> SELECT COUNT(*) FROM dba_invalid_objects;
SQL> @?/rdbms/admin/utlrp.sql
Falls Sie wieder auf den LOCAL UNDO Modus wechseln wollen, gehen Sie analog zum Ausschalten vor.
SQL> ALTER DATABASE LOCAL UNDO ON;
Oracle erzeugt dabei automatisch einen UNDO-Tablespace für die PDB. Dazu der Auszug aus der Alertdatei:
PDB_O12C(3):CREATE SMALLFILE UNDO TABLESPACE undo_1 DATAFILE '/u01/app/oracle/oradata/o122cdb/pdb_o12c/system01_i1_undo.dbf'
SIZE 104857600 AUTOEXTEND ON NEXT 5242880 MAXSIZE 34359721984 ONLINE
FAZITSie haben nun einen Eindruck davon bekommen, was auf Sie zukommen kann, wenn Sie auf die Container-Architektur umstellenund dabei auch gleich noch einen Versions-Upgrade durchführen möchten.Es sei an dieser Stelle aber noch einmal ausdrücklich erwähnt, dass dieser Tipp keine Besonderheiten wie RAC, Data Guard, ASModer andere Oracle Optionen berücksichtigt. Deshalb kann nicht vorhergesagt werden, welche zusätzlichen Hürden sich Ihnenin den Weg stellen …
Bei Oracle Datenbanken werden viele Log-Files, Trace-Files, Audit-Files etc. erzeugt, die an unterschiedlichen Orten im Dateisystem und in der Datenbank gespeichert werden.
Bereits seit Oracle 11g gibt es den Parameter diagnostic_dest, der den Pfad angibt, wo die Trace-Files, Log-Files, das Alertlog, etc. abgelegt werden. Dieser Parameter zeigt auf den zentralen Ort, in dem alle Information zusammengefasst werden: das Diagnostic Repository.
Oracle stellt ein leistungsfähiges Tool zur Verfügung, das neben Dateien löschen, bei auftretenden ORA-Fehlern auch zugeordnete Incidents und Problems darstellen kann. Außerdem können Sie mit diesem Tool alle notwendigen Files für den Oracle Support komfortabel zusammenstellen und zippen, das Alertlog anzeigen, sowie Trace-Dateien im laufenden Betrieb löschen. In diesem Monatstipp wird nun näher beleuchtet, wie aufgetretene Incidents (Vorfälle) und Problems (Probleme) ermittelt und die zugehörigen Counter zurückgesetzt werden können. Die Informationsquelle für die aufgetretenen Problems und Incidents stellt die Tabelle V$DIAG_INFO dar.
Über die Tabelle V$DIAG_INFO ermitteln wir zunächst die Anzahl der aufgetretenen Probleme und Incidents:
SQL> select name,value from v$diag_info;NAME VALUE--------------------- --------------------------------------------Diag Enabled TRUEADR Base D:\APP\ROLANDADR Home D:\oracle\diag\rdbms\o19c\o19cDiag Trace D:\oracle\diag\rdbms\o19c\o19c\traceDiag Alert D:\oracle\diag\rdbms\o19c\o19c\alertDiag Incident D:\oracle\diag\rdbms\o19c\o19c\incidentDiag Cdump D:\oracle\diag\rdbms\o19c\o19c\cdumpHealth Monitor D:\oracle\diag\rdbms\o19c\o19c\hmDefault Trace File D:\oracle\diag\rdbms\o19c\o19c\trace\o19c_ora_9620.trcActive Problem Count 2Active Incident Count 2
Um die zugrundeliegenden Problems bzw. Incidents genauer zu analysieren, wird der Automatic Diagnostic Report CommandInterpreter [ADRCI] auf OS-Ebene aufgerufen.
C:\Windows\System32>adrciADRCI: Release 12.2.0.1.0 - Production on Mo Jun 26 11:11:12 2017Copyright (c) 1982, 2017, Oracle and/or its affiliates. All rights reserved.ADR base = "D:\app\roland"adrci>
Die Ausgabe oben zeigt das per Default gesetzte ADR BASE an. Durch Aufruf der Tool-Hilfe mittels help können Sie sich weitere Informationen anzeigen lassen.
Der Output sieht dann folgendermaßen aus:
adrci> help HELP [topic] Available Topics: CREATE REPORT ECHO ESTIMATE EXIT HELP HOST IPS PURGE RUN SELECT SET BASE SET BROWSER SET CONTROL SET ECHO SET EDITOR SET HOMES | HOME | HOMEPATH SET TERMOUT SHOW ALERT SHOW BASE SHOW CONTROL SHOW HM_RUN SHOW HOMES | HOME | HOMEPATH SHOW INCDIR SHOW INCIDENT SHOW LOG SHOW PROBLEM SHOW REPORT SHOW TRACEFILE SPOOL There are other commands intended to be used directly by Oracle, type "HELP EXTENDED" to see the list
Um das korrekte ADRCI-Home anzuzeigen, lassen wir uns alle verfügbaren ADRCI-Homes mit dem Befehl show homes auflisten.
adrci> show homesADR Homes:diag\clients\user_roland\host_1513561619_107diag\clients\user_roland\host_1513561619_82diag\clients\user_SYSTEM\host_1513561619_107diag\clients\user_SYSTEM\host_1513561619_82diag\rdbms\o12c\o12cdiag\rdbms\o12c2\o12c2diag\tnslsnr\Host02\listenerdiag\tnslsnr\Host02\listener_o12c2adrci>
Setzen Sie dann per set Befehl das richtige ADRCI-HOME:
adrci> set home diag\rdbms\o12c2\o12c2adrci> show homeADR Homes:diag\rdbms\o12c2\o12c2
Nachdem nun das richtige ADRCI-HOME gesetzt wurde, beginnen wir mit der Auswertung der in V$DIAG_INFO angezeigten Problems und Incidents.
Dafür stehen Ihnen die Befehle SHOW PROBLEM oder SHOW INCIDENT zur Verfügung. Diese Befehle verschaffen schnell einen guten Überblick über den Datenbankserver.
adrci> SHOW PROBLEMADR Home = D:\app\roland\diag\rdbms\o12c2\o12c2:***************************************************************PROBLEM_ID PROBLEM_KEY LAST_INCIDENT LASTINC_TIME---------- ----------------- ------------- -------------------1 ORA 63999 69258 2017-06-26 09:52:102 ORA 7445 [kslwtbctx] 74242 2017-06-26 09:55:322 rows fetched
Die Ausgabe zeigt die PROBLEM_KEYs ORA 7445 und ORA 63999, die den gleichnamigen Oracle-Fehlermeldungen zugrunde liegen, mit den zugeordneten INCIDENT Nummern an.
Ausgabe gelistet nach den aufgetretenen Incidents:
adrci> SHOW INCIDENTADR Home = D:\app\roland\diag\rdbms\o12c2\o12c2:***************************************************************INCIDENT_ID PROBLEM_KEY CREATE_TIME----------- -------------------- -------------------69258 ORA 63999 2017-06-26 09:52:1074242 ORA 7445 [kslwtbctx] 2017-06-26 09:55:322 rows fetched
Eine detailliertere Ausgabe zum aufgetretenen Incident bekommen Sie über die Abfrage:
adrci> show incident -mode detail
==> gibt Details zu ALLEN Incidents
adrci> show incident -mode detail -p "incident_id=<Nr>"
==> gibt Details zu einer speziellen Incident IDBeispielausgabe für Incident 74242:
adrci> show incident -mode detail -p "incident_id=74242" ADR Home = D:\app\roland\diag\rdbms\o12c2\o12c2:***********************************************************************************************************************************INCIDENT INFO RECORD 1********************************************************** INCIDENT_ID 74242 STATUS ready CREATE_TIME 2017-06-26 09:55:32.403000 +02:00 PROBLEM_ID 3 CLOSE_TIME <NULL> FLOOD_CONTROLLED none ERROR_FACILITY ORA ERROR_NUMBER 7445 ERROR_ARG1 kslwtbctx ERROR_ARG2 ACCESS_VIOLATION ERROR_ARG3 ADDR:0x30 ERROR_ARG4 PC:0x7FF6E2F9A5AF ERROR_ARG5 UNABLE_TO_READ ERROR_ARG6 <NULL> ERROR_ARG7 <NULL> ERROR_ARG8 <NULL> ERROR_ARG9 <NULL> ERROR_ARG10 <NULL> ERROR_ARG11 <NULL> ERROR_ARG12 <NULL> SIGNALLING_COMPONENT <NULL> SIGNALLING_SUBCOMPONENT <NULL> SUSPECT_COMPONENT <NULL> SUSPECT_SUBCOMPONENT <NULL> ECID <NULL> IMPACTS 0 CON_UID 0 PROBLEM_KEY ORA 7445 [kslwtbctx] FIRST_INCIDENT 74242 FIRSTINC_TIME 2017-06-26 09:55:32.403000 +02:00 LAST_INCIDENT 74242 LASTINC_TIME 2017-06-26 09:55:32.403000 +02:00 IMPACT1 0 IMPACT2 0 IMPACT3 0 IMPACT4 0 KEY_NAME Client ProcId KEY_VALUE ORACLE.EXE.4072_11416 OWNER_ID 1 INCIDENT_FILE D:\app\roland\diag\rdbms\o12c2\o12c2\trace\o12c2_ora_11416.trc OWNER_ID 1 INCIDENT_FILE D:\app\roland\diag\rdbms\o12c2\o12c2\incident... ...\incdir_74242\o12c2_ora_11416_i74242.trc
Die Ausgabe zeigt, dass eine Zugriffsverletzung vorlag.
Diese Informationen können nun verwendet werden, um ein sogenanntes Incident- bzw. Problempaket zu erzeugen, welches anschließend an den Oracle Support hochgeladen werden kann.
adrci> ips pack incident 69258 in C:\tempGenerated package 2 in file C:\temp\ORA63999_20170626152636_COM_1.zip,mode completeadrci> ips pack problem 1 in C:\tempGenerated package 1 in file C:\temp\IPSPKG_20170626152435_COM_1.zip,mode complete
Auch im Alertlog werden Problems mit den entsprechenden ORA-Fehlermeldungen mitprotokolliert:
Mon Jun 26 09:09:15 2017Errors in file D:\APP\ROLAND\diag\rdbms\o12c\o12c\trace\o12c_ckpt_7244.trc:ORA-63999: Datenträgerfehler bei DatendateiORA-01122: Überprüfung von Datenbank-Datei 6 nicht erfolgreichORA-01110: Datendatei 6: 'D:\TEMP\DATA01.DBF'ORA-01210: Datendateiheader hat physikalischen FehlerMon Jun 26 09:09:15 2017Errors in file D:\APP\ROLAND\diag\rdbms\o12c\o12c\trace\o12c_ckpt_7244.trc:ORA-63999: Datenträgerfehler bei DatendateiORA-01122: Überprüfung von Datenbank-Datei 6 nicht erfolgreichORA-01110: Datendatei 6: 'D:\TEMP\DATA01.DBF'ORA-01210: Datendateiheader hat physikalischen FehlerMon Jun 26 09:09:16 2017System state dump requested by (instance=1, osid=7244 (CKPT)), summary=[abnormal instancetermination].
Diese Fehlermeldungen (für Incidents) würden von Oracle nun für die Dauer von einem Jahr vorgehalten und in V$DIAG_INFO als Alarmcounter solange angezeigt werden. Der SHOW CONTROL Aufruf gibt nähere Auskunft zu den Aufbewahrungsfristen.
adrci> SHOW CONTROLADR Home = D:\app\roland\diag\rdbms\o12c2\o12c2:************************************************************ADRID SHORTP_POLICY LONGP_POLICY LAST_MOD_TIME---------- ------------- ------------ --------------------946440162 720 8760 2017-05-03 12:18:21
SHORTP_POLICY (kurzfristig) ist standardmäßig auf 30 Tage (720 Stunden) voreingestellt.
==> verwaltet die Trace- und Core-Dump-Dateien.
LONGP_POLICY (langfristig) ist standardmäßig auf 365 Tage (8760 Stunden) voreingestellt.
==> verantwortlich für Incidents (Vorfälle) und Health-Monitoring Warnungen.
Ebenso legt der Wert auch fest, wann veraltete Alert_<nummer>.xml Dateien gelöscht werden dürfen.
Um den Counter wieder auf null zurückzusetzen steht Ihnen der purge Befehl zur Verfügung:
adrci> purge -i <Incident id> [<Incident id> <Incident id> ...]adrci> purge -age < älter als Minuten> -type incident
Beispiel für Incident:
adrci> purge -i 69258 74242adrci> purge -age 5 -type incident
Angewendet auf das vorherige Beispiel:
adrci> purge -age 5 -type incidentadrci> show incidentADR Home = D:\app\roland\diag\rdbms\o12c2\o12c2:*************************************************************************0 rows fetchedSQL> select name,value from v$diag_info;NAME VALUE---------------------- ------------------------------------------Diag Enabled TRUEADR Base D:\APP\ROLANDADR Home D:\APP\ROLAND\diag\rdbms\o12c2\o12c2Diag Trace D:\APP\ROLAND\diag\rdbms\o12c2\o12c2\traceDiag Alert D:\APP\ROLAND\diag\rdbms\o12c2\o12c2\alertDiag Incident D:\APP\ROLAND\diag\rdbms\o12c2\o12c2\incidentDiag Cdump D:\app\roland\diag\rdbms\o12c2\o12c2\cdumpHealth Monitor D:\APP\ROLAND\diag\rdbms\o12c2\o12c2\hmDefault Trace File D:\APP\ROLAND\diag\rdbms\o12c2\o12c2\trace\o12c2_ora_9620.trcActive Problem Count 0Active Incident Count 0
Um eine saubere Datenbank zu betreiben und zu erhalten, bedarf es ein wenig adminstrativer Tätigkeiten. ADRCI ist eines der Tools, die dem DBA die Arbeit zum großen Teil erleichtern.
Wenn wir Sie neugierig gemacht haben und Sie weitere nützliche Informationen zu ADRCI benötigen, besuchen Sie doch einfach unseren Reorg & Wartungskurs.
Wir hatten in einem Projekt das Problem, einen Ref Cursor auszuwerten, von dem nicht bekannt war, wie viele Spalten er zurückliefert. Dies ist aber notwendig, um eineentsprechende Anzahl an Parametern (bzw. Records/Arrays) zu definieren.
Seit Version 11g kann man nun einen Ref Cursor in einen dbms_sql Cursor umwandeln. Dann ist es möglich, die Spaltenzahl zu ermitteln und dynamisch Variablen für diese Spalten zu definieren.
Zuerst benötigen wir ein Package, das den Datentyp Ref Cursor als Rückgabewert erlaubt:
Dann definieren wir ein Package Body mit einer Funktion, die einen Ref Cursor zurückgibt:
Zu guter Letzt schreiben wir einen anonymen Block, der dann den Ref Cursor aus der Funktion zurückbekommt.Et voila, wir können mit einer beliebigen Spaltenanzahl das Ergebnis weiterverarbeiten:
Wer mit APEX und ORDS zusammenarbeitet ist immer froh, wenn er eine Übersicht über die aktuellen ORDS Parameter findet.Anbei haben wir einige zusammengestellt:Sie erhalten eine Komplett-Übersicht aller Oracle ORDS Parameter für die Oracle Version 19.4 hier.Aktuell ist derzeit die Oracle ORDS Version 19.4.6 (1.6.2020)Parameter in der Datei defaults.xml können manuell mit einem Texteditor geändert werden, oder auch durch:
Die folgenden Parameter betreffen die Datenbank
oder bei einem Failover Eintrag
<entry key="db.connectionType">customurl</entry>
<entry key="db.customURL">jdbc:oracle:thin:@(DESCRIPTION=(FAILOVER=ON)(ADDRESS_LIST=
(LOAD_BALANCE=ON)(ADDRESS=(PROTOCOL=TCP)(HOST=muniqsoft-training.de)(PORT=1521)))
(CONNECT_DATA=(SERVICE_NAME=ISPRD)))|</entry>
Wenn es Probleme beim Verbinden gibt (z.B. Could not map a database) sollte versucht werden, eine Verbindung der Datenbank von der Shell/DOS direkt zur Datenbank durchzuführen mit:
Die folgenden 4 Parameter sind verantwortlich für das Debugging und LoggingHinweiß: Für Produktivmaschinen sollte Debuggung auf "false" stehen !
Wenn Sie eine eigene Datei in einem selbst gewählten Pfad für die Fehlermeldungen verwenden möchten:
<entry key="error.externalPath">/opt/tomcat/latest/logs</entry>
Diese Datei muss das Format {servererrorcode}.html besitzenalso z.B 404.html oder 500.htmlDie nächsten 4 Parameter kümmern sich um die Konfiguration der internen Java Parameter und spielen für die Performance des REST Service eine wichtige Rolle:
{servererrorcode}.html besitzen
also z.B 404.html oder 500.html
Maximale Anzahl der Zeilen definieren,die bei einer Abfrage zurückommen dürfen (Default: 500)
REST Enables SQL freischalten:
Datenbank API via REST freischalten:
database.api.enabled
oder auf der Kommandozeile:
Pluggable Database API abschalten (ab 19.2):
database.api.management.services.disabled
oder wieder auf der Kommandozeile:
java -jar ords.war set-property database.api.management.services.disabled true
Manchmal hat man doch Sehnsucht nach der alten Zeit, in unserem Fall nach einer Oracle Forms 6i Version aus dem Jahre 1998.Im folgenden Tipp versuchen wir dieses alte Release nochmal zum Laufen zubringen. Ein kleiner Spoiler vorab: DAS GANZE IST NICHT SUPPORTED !Das bedeutet, nicht von mir, noch von Oracle. Also bitte erstellen Sie von allem was Ihnen lieb und teuer ist ein funktionierendes (und damit getestetes) Backup.Vorbereitung:Wir besorgen uns eine alte Oracle Forms6i / Reports6i Version (Oracle Developer 6i) (Die gab es damals noch auf CD :-) )Wenn Sie einen Wartungsvertrag mit Oracle haben, besorgen Sie sich bitte zusätzlich die Patches 3 und 19.Installieren Sie das Grundprodukt und danach den Patch 18.
Jetzt kommt der spannende Teil (hat mich fast 2 Tage gekostet):Tauschen Sie die Dateien (Pfad c:\orant\bin) nn60.dll und nnmb60.dll aus dem Patch 3 gegen die aktuellen aus.Wenn Sie die Dateien nicht zur Verfügung haben, einfach die beiden Namen in die Suchmaschine Ihrerer Wahl eingeben und schon findet man zwei Treffer zum Download.Praktische Einträge in der Registry für die Oracle Forms6i Software:Pfad: Computer\HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\ORACLE\HOME0
Nun in der SQLNET.ORA auf der Serverseite folgendes editieren:
Anmerkung: Eine Oracle 18c DB verwendet einen anderen Hash-Algo für die Passwort-Verschlüsselung im Vergleich zu Oracle 8.Wir sind durch diese Einstellung also auf dem Sicherheitsniveau einer Oracle 8 Datenbank. Kredikarten-Daten würde ich in der DB nicht speichern :-)Oracle Forms 6i arbeitet mit dem Zeichensatz AL16UTF8 nicht zusammen, deswegen müssen wir den bei der XE DB als Default eingestellten Zeichensatz ändern.Achtung das sollte direkt nach der Installation der DB und noch vor dem Datenimport passieren !!!
Nun machen wir einen Test auf den alten Oracle 8 Passwort-Hash (sonst bekommen Sie bei der Forms Anmeldung immer einen ORA-01017 Fehler zurück):
Neues Passwort für den Benutzer SCOTT setzen
Nun sollte das "alte" Password wieder zu sehen sein:
Jetzt gehen wir in die Client-Datei c:\orant\net80\tnsnames.ora und tragen ein:
Versuchen Sie sich jetzt von Forms bei der DB anzumelden: File => Connect
Und nun viel Spaß mit nostalgischen Forms Sessions.Wenn Sie Ihre alten Forms 6i Masken von uns auf Oracle APEX portieren lassen möchten, melden Sie sich gerne bei uns, wir helfen Ihnen gerne...
Oracle APEX 20.1 ist gerade mal 4 Wochen heraus und schon gibt es den ersten Patch, der ein paar praktische Bugfixes mitbringt (u.A. die falsche Timeout Warnung wird behoben)Sie können den Patch von Oracles Support Seite herunterladen und in einer Minute installieren.Vorgehensweise:1. Webserver stoppen1 a, Sie haben das EPG im Einsatz:
Wenn ein Port <>0 zurückommt, dann haben Sie das EPG im Einsatz. Dann merken Sie sich den Port bitte.
1 b, Sie haben den TomCat im Einsatz
1 c, Sie haben TomCat und Apache als Reverse Proxy im Einsatz:
2. Patch einspielen (z.B. in den Ordner /u01/software)
3. Image Ordner aktualisieren3 a. bei EPG (hier werden die Bilder in der datenbank gespeichert)
3 b, bei TomCat (ohne Apache)Prüfen Sie bitte zuerst, ob das Verzeichnis dort existiert (kann je nach Installation auch auf einem anderem Pfad liegen)
3 c, Bei TomCat (mit Apache)
4. Webserver wieder starten4 a. Bei EPG:
4 b, Tomcat ohne Apache
4 c, Sie haben TomCat und Apache als Reverse Proxy im Einsatz:
5. Schlußprüfungen: 5 a. Patch installiert:
SELECT patch_version, installed_onFROM apex_patchesWHERE patch_number = 30990551;
Gibt es ungültige Objekte?
Dies und noch mehr lernen Sie bei einem unserer fünf verschiedenen APEX-Kurse, die wir seit 2005 unterrichten!
Wer seine Postgres Datenbank liebt/braucht, sollte regelmäßig ein Backup von ihr machen.Der nachfolgende Tipp soll ein Skript dafür zur Verfügung stellen. Bitte testen Sie das Skript bitte ausgiebif durch bevor Sie es auf einer Produktiv-Datenbank ausführen.Wir übernehmen keine Haftung/Gewähr für evtl Fehler.
Kleine Erklärung zum Postgres Datenbank Backup Skript:Im ersten Block werden die Variablen definiert. Prüfen Sie hier bitte, ob alle Voreinstellungen bei Ihnen passen.in der Variablen WAL_START steht die letzte WAL-Datei vor dem Backup. Damit benötigen wir alle WAL Dateien, die danach angefallen sind, um das Backup wieder funktionstüchtig zu bekommen.BACKUP_START setzt die Datenbank in den Backup-Modus. Das ist wichtig, weil wir danach erst Dateien aus der Datenbank Online kopieren dürfen.Der Backup Befehltar -cjf $DAY_FOLDER --exclude='pg_wal' *erzeugt ein Backup im Tar-Zip Format vom Hauptordner der Datenbank. Achtung: Eventuell vorhandene externe Tablespace-Ordner werden dadurch nicht mitkopiert!!!BACKUP_END nimmt die Postgres Datenbank wieder aus dem Backupmodus heraus.Der find Befehl findet alle nach Begin des Backups erzeugten WAL-Dateien und kopiert die auch in den Backup-Ordner.Der nachfolgende Befehl packt die WAL Dateien auch in eine TAR-Datei.Zusätzlich wird ein Restore Skript erzeugt. Dieses fragt sich beim Start auf welche Zeit denn zurückgesetzt werden soll. Wenn Sie auf den letztmöglichen Zeitpunkt zurückgehen möchten, geben Sie bitte latest ein.Danach wird noch eine kleine Nachricht über den Erfolg des Backups ausgegeben.HAPPY BACKUPFür weitere Fragen rund um Postgres, besuchen Sie doch einen unserer Postgres-Kurse.
Wir hatten jüngst eine (vermeintlich) einfache Query, die aber 5 Min lief. Sie lautete:
Warum lief sie so lange?Wenn man sich den Ausführungsplan ansieht, stellt man fest, dass eine der internen Tabellen keine Statistiken besitzt.Tipp 1:Die Tabelle X$KTFBUE hat keine Statistiken und bekommt auch keine, weil es sehr lange dauern könnte diese zu berechnen (ist also ein Feature und kein Bug)Übrings, bekommt die Tabelle auch keine Statistiken durch den Aufruf:
Achtung, es sind schon Fälle beobachtet worden, da lief die Statistikerzeugung über 8 Stunden !Also bitte nicht einfach nur:
sondern zuerst:
Laufzeit bei uns: 14.8s.Oder als abgeschätzte Statistik (5%):
Laufzeit bei uns: 6.1s.Oder als abgeschätzte, parallelisierte Statistik:
Laufzeit bei uns: 6.0s (bringt also bei unserer Hardware nichts, evtl. haben Sie ja eine bessere Maschine :-) )P.S.: Auch mit noch kleineren Sample-Sizes (1%, 0.1% wurde es bei uns nicht schneller)Wer auf die Berechnung der Statistik verzichten möchte und sich gleich traut, einfach selbst den Statistik-Wert einzutragen (traue keiner Statistik, ....)
Bei uns gab es keine signifikanten Unterschiede in der Laufzeit, auch wenn wir Faktor 10 die Statistik zu hoch eingesetzt hatten, aber das ist hier jetzt unsupported ...Oder noch besser zuerst:Tipp 2: Leeren Sie den Mülleimer:
und erzeugen Sie neue Statistiken für den Mülleimer:
Am Besten schaltet man dem Mülleeimer sowieso ganz aus (sagt auch Oracle):
Behind the scenes:Wer wissen möchte, wieviele Zeilen nun in der Tabelle X$KTFBUE enthalten sind:
Laufzeit der Query nach den Tipps:0.031 Sekunden, das kann sich doch sehen lassen, oder ?Mike Dietrich von Oracle hat das Thema Fixed Table Stats in einem seiner Blogs auch schon mal thematisiert.
Mit dem Datum 21.10.2020 kam die Oracle APEX 20.2 Version nun doch sehr überrraschend frühzeitig heraus (im Vergleich zu den letzten Jahren). Aber gute Nachrichten kann man in den aktuell schweren Zeiten ja immer gebrauchen ... :-). Wir haben uns natürlich gleich am Tag 1 der Veröffentlichung um eine Migration unserer APPs auf das neue Release gekümmert.
APEX 20.2 Download
wir haben mal das relativ neue Installationsskript apexsilentins.sql für die Installation verwendet.Es ersetzt die folgenden Skripte:
Ausserdem erstellt es eine neue ACL (power_users.xml) und der Benutzer APEX_PUBLIC_USER wird automatisch entsperrt (endlich!)Dadurch benötigt es jedoch auch mehr Parameter als das alte apexins.sql Skript. Der Aufruf lautet hier:
Parameter 1: Name des Tablespace für den Application Express Application Benutzer (APEX_200200)Parameter 2: Name des Tablespace für den Application Express files user (FLOWS_FILES)Parameter 3: Name des temporären Tablespace (bzw. Tablespace Gruppe) für Sortierungen / Indexerstellung / Sort Merge Joins u.v.w.Parameter 4: Virtuelles Verzeichnis für APEX Bilder/CSS/Javascript DateienParameter 5: Passwort für APEX_PUBLIC_USERParameter 6: Passwort für APEX_LISTENERParameter 7: Passwort für APEX_REST_PUBLIC_USERParameter 8: Passwort für Workspace Internal APEX internal ADMIN user (Achtung, Sie müssen sich hier an strenge Passwort-Richtlinien erhalten, also bitte nicht APEX123 verwenden :-) )Also als Beispiel:
Die Installationszeit betrug auf unserem Server: 15 minWenn Sie einen Webserver verwenden z.B. Apache TomCat Version 9.x, dann kopieren Sie bitte den images Ordner aus dem Apex Zip File aufWindows: C:\Program Files\Apache Software Foundation\Tomcat 9.0\webappsLinux: /opt/tomcat/latest/webappsals Ordner i !, bzw. den Namen, den Sie bei der Installation als Parameter 4 angegeben haben. Wenn es dort schon einen Ordner gibt, bietet es sich an, den erstmal nur umzubennen und nicht gleich zu löschen!
Wenn Sie das interne EPG verwenden (also keinen externen Werserver), muss noch zusätzlich das folgende Skript gestartet werden:@apex_epg_config.sql <Pfad zu den Images>Achten Sie aber darauf, den Ordner-Namen apex nicht mit im Pfad anzugeben, weil das Skript ihn selbst dazufügt, also wenn die Bilder unter (Windows: c:\temp\apex oder Linux: /tmp/apex) liegen, lautet der Aufruf:
Wer schon mal mit dem JSON Date Datentyp gearbeitet hat, ist sich dessen Problemen sicherlich bewusst.Wir wollen uns im nachfolgenden Atrikel dem Problem mal annehmen:Nehmen wir mal die in Oracle 21c neue eingeführte Funktion json_scalar und json_serializeJSON_SCALAR wandelt einen Text/ ein Datum oder eine Anzahl in eine interne BLOB Repräsentanz.
Wenn wir das zurückwandeln passiert folgendes:
Da fallen einem gleich zwei Problemzonen ins Auge:1. "" am Anfang / Ende2. ein T zwischen Datum und UhrzeitDer erste Versuch scheitert deswegen auch:
Das liegt an der etwas eigenartigen Behandlung von Gänsefüßen bei Oracle Strings
oder auch
auch das geht schief:
Deshalb lösen wir das Problem mit zwei Funktionen:1. Wir ersetzen "" durch nix2. Wir konvertieren den String mit Hilfe der Funktion to_date und dem Format String 'YYYY-MM-DD"T"HH24:MI:SS'
Weitere Tipps erhalten Sie in einem unserer Oracle Kurse...
Ein Bild sagt ja bekanntlich mehr als 1001 Worte, deswegen ist es manchmal ganz praktisch sich die Belegung seines Tablespace mal grafisch anzuzeigen.
WITH FUNCTION tbs_map ( p_file_id IN NUMBER DEFAULT 1, p_width IN NUMBER DEFAULT 200, p_blocks IN NUMBER DEFAULT 128) RETURN CLOB IS t_clob CLOB:=empty_clob(); t_clob_out CLOB:=empty_clob(); t_clob_len INT; tbs_name VARCHAR2(128); tbs_free_space NUMBER; tbs_file_size NUMBER; tbs_block_size INT; cnt INT:=0; BEGIN t_clob:=' '; FOR c IN (select tablespace_name,round(sum(bytes)/1024/1024) sum_bytes INTO tbs_name,tbs_free_space from dba_free_space where file_id=p_file_id group by tablespace_name ) LOOP tbs_name:=c.tablespace_name; tbs_free_space :=c.sum_bytes; END LOOP; IF tbs_name IS NULL THEN RETURN 'Datafile '||p_file_id||' not existing'; END IF; FOR c IN (select round(bytes/1024/1024) file_size,block_size from v$datafile where file#=p_file_id) LOOP tbs_file_size := c.file_size; tbs_block_size := c.block_size; END LOOP; t_clob_out :='Tablespace='||tbs_name ||', File='||p_file_id||', Size='||tbs_file_size||', MB Free='||tbs_free_space|| ' MB, Blocks='||p_blocks||', (c) 2025 by Muniqsoft Training '||chr(10); --t_clob:=' '; FOR c IN ( SELECT block_seg,replace(lpad('.',ceil(sum_blocks/p_blocks)+1,CASE segment_type WHEN 'TABLE' THEN 'T' WHEN 'INDEX' THEN 'I' WHEN 'INDEX PARTITION' THEN 'J' WHEN 'LOBSEGMENT' THEN 'L' WHEN 'LOB PARTITION' THEN 'L' WHEN 'CLUSTER' THEN 'C' WHEN 'TYPE2 UNDO' THEN 'U' WHEN 'ROLLBACK' THEN 'U' WHEN 'TABLE PARTITION' THEN 'P' WHEN 'TABLE SUBPARTITION' THEN 'P' WHEN 'LOBINDEX' THEN 'X' WHEN 'NESTED TABLE' THEN 'N' WHEN 'O' THEN 'O' ELSE '?' END),'.','') as stype FROM ( SELECT block_seg,sum_blocks,segment_type ,row_number() over (partition by block_seg order by sum_blocks desc) rn from ( select floor(block_id/p_width) block_seg ,sum(blocks) sum_blocks,segment_type from (select block_id,blocks,segment_type from dba_extents where file_id=p_file_id UNION ALL select block_id, blocks, 'O' from dba_free_space where file_id=p_file_id ) group by floor(block_id/p_width),segment_type order by 1)) where rn=1) LOOP dbms_lob.writeAppend(t_clob,length(c.stype),c.stype); cnt:=cnt+1; END LOOP; t_clob_len:= (dbms_lob.getlength(t_clob))/p_width; FOR i IN 1 .. ceil(t_clob_len) LOOP dbms_lob.writeAppend( t_clob_out, p_width+7, lpad(to_char((i-1)*p_width*tbs_block_size),5,'0')||' '||DBMS_LOB.SUBSTR(t_clob,p_width,(i-1)*p_width+6)||chr(10) ); END LOOP; RETURN DBMS_LOB.SUBSTR(t_clob_out,dbms_lob.getlength(t_clob_out)-6,1) || chr(10)||'(O)=Leer, (T)able, (I)ndex, (J)ndex Partition, (P)artition, (U)ndo/Rollback, (C)luster, (L)obsegment, (N)ested Table, Lob Index(x)'; END; select TBS_MAP(p_file_id =>2, p_blocks=>128,p_width=>128) from dual; /
Folgende Parameter können übergeben werden:p_file_id Nummer der Datendatei (aus v$DATAFILE)p_blocks Anzahl der Blöcke, die zu einem Zeichen zusammengefasst werden sollen (Derzeit nur sinnvoll mit Wert 128 einsetzbar, andere Werte werden bald nachgereicht)Das bedeutet, wenn 128 Tabellen Blöcke hintereinander leiegen , wird dafür ein (T) ausgegeben für 256 Tabellenblöche zwei (TT) u.s.w.Liegen in diesen 128 Blöcken mehrere verschiedene Objekte, wird das größte nur angezeigt!p_width= Ausgabebreite in Zeichen, alle mit Monitoren größer als 40" können da natürlich die Breite mehr ausreizen :-)Sollte der SELECT lange laufen, fehlt ihnen evtl eine Statistik auf X$KTBFUE (siehe Link unten im Artikel)Die Ausgabe sieht dann z.B. so aus
So bekommt man doch gleich einen Überblick, ob eine Reorg sich auf dem Tablespace lohnt.Un unserem Fall ja, weil viele (O) am Ende zu finden sind
Wenn mann seine ersten Schritte mit PostgreSQL durchführt, ist meist das erste Problem, dass man sich nicht Remote mit der DB verbinden kann. Die Datenbank lauscht standartmäßig auf Clientanfragen erst einmal nur lokal.Um das zu ändern öffnet man die Datei postgresql.conf.Dort sucht man nach der Zeile listen_addresses und setzt sie auf *
listen_addresses = '*' # what IP address(es) to listen on;
# comma-separated list of addresses;
# defaults to 'localhost', '*' = all
Jetzt startet man die Datenbank über z. B. den Systemd Service neu und schon horcht sie auch auf Verbindungen die nicht vom lokalen System kommen.Das nächste Probleme folgt aber direkt jetzt. Man kann sich nicht direktmit jedem Benutzer Remote anmelden dazu muss man eine Einstellung in einerweiteren Config Datei treffen. Dort findet man z. B. folgende Zeile:
host all all localhost trust
Hier mal eine kleine Erklärung für diese Zeile.Der erste Eintrag steht für die Verbindungsart. Der 2te für die Datenbankauf die sich verbunden werden soll. Der dritte Eintrag ist für den Userdort kann man einen bestimmten User angeben der z. B. nur auf eine bestimmteDatenbank zugreifen kann. Die Adresse kommt im vierten Eintrag so kann manz. B. entweder ein ganzes Subnetz oder auch einfach mittels 0.0.0.0 das ganze Internet erlauben. Als letztes kommt noch die AuthentizifierungsmethodeWenn Sie genau wissen wollen welche Werte sie dort alles genau eintragen könnenfinden Sie hier die Doc Seite von Postgre zur pg_hba.conf (https://www.postgresql.org/docs/current/auth-pg-hba-conf.html).Wenn Sie jetzt z. B. wollen das jeder auf diese Datenbank zugreifen kannschreiben Sie ganz nach oben folgende Zeile:
hostssl all all all
Ja mir ist bewusst das md5 geknackt wurde. Deshalb nutzen wir als Verbindungsarthostssl. Das lässt nur eine Verbindung zu wenn diese mittels SSL verschlüsselt ist.Noch ein kleiner Hinweis zum Ende.Möchte man sich mittels psql zu einer Datenbank verbinden muss der Benutzername kleingeschrieben sein.Das hat mich auch ca. 10 bis 15 Minuten gekostet bis ich da drauf gekommen bin.
Wenn man mit zwei Datenbanken parallel arbeiten möchte, stellt sich immer die Frage, wie geht das am Besten?Wir wollen hier mal die REST Schnittstelle als Verbindung zwischen Oracle und Postgres verwenden.Wir verwenden hier PostgRESThttps://postgrest.org/en/v7.0.0/Installationsverzeichnis aussuchen:
Software herunterladen:
Auspacken:
REM Rest Service Dienst starten
Schema und Beispieltabelle anlegen:
Rolle anlegen
Nur Leserechte auf Schema
Anmelde Benutzer anlegen:
vi tutorial.conf
Passwort eintragen:
Mit Ihrem Passwort gehen Sie bitte in die Webseite und führen folgende Schritte aus
Verwenden Sie ein zweite Session:Lesetest:
Schreibtest:
Beispiele für Lesefilter:
Eine Zeile anzeigen
Weitere Beispiele: https://postgrest.org/en/v7.0.0/api.htmlInsert neue Zeile
Update (auf alle Zeilen)
Update (auf eine Zeile (alle Spalten müssen angegeben werden!))
Delete (eine Zeile)
Sehen wir uns mal die Seite von Oracle aus an. Wie kann man die Postgres Schnittstelle ansprechen?Dafür bietet sich das Package apex_web_service an, das installiert ist, wenn Sie auch APEX/ORDS installiert haben.Wir schreiben uns ein kleines Package, das die Daten im JSON Format an die Postgres REST Schnittstelle übergibt:
und der dazugehörige Body. Bitte beachten Sie, dass der Bearer Schlüssel in Zeile 11 angepasst werden muss. Diese haben Sie im Schritt auf der Seite https://jwt.io/#debugger-io(siehe oben) bekommen.Wenn der Schlüssel nicht passt, bekommen Sie eine Fehlermeldung, dass Sie keine Rechte auf der Tabelle haben.Passen Sie auch bitte die IP Adresse vom Ziel Server an (bei uns 172.30.30.8)
Als Bonus-Track schreiben wir uns einen Trigger, der das obige Oracle Package nutzt und alle Änderungen auf Oracle Seite in der Tabelle in eine gleiche Tabelle auf Postgres synchon spiegelt.Hinweis die Tabelle (mit Primary Key) muss in Postgres jedoch angelegt werden:
Beispiele zum Packageaufruf:
Beispiele zum Trigger-Testen:
Nun kann man Oracle und Postgres wunderbar miteinander verbinden. Weitere Tipps & Tricks erfahren Sie u.a. in unserm Oracle ORDS Kurs.
Der Workspace Manager dient zur Versionierung von Tabellendaten in verschieden Versionen (Workspaces)Vorteile
Vorbereitungen:
Sie können eine Administrationsrolle mit allen Rechten für die Workspacebearbeitung vergeben:
Folgende Einzelrechte können vergeben werden:
Beispiel:
Folgendes gilt für die Tabellen:
Beispiel:Tabelle für den Workspace Manager aktivieren:
Zwei Workspaces einrichten:
In den ersten Workspace wechseln:
Durchführen von Änderungen in der Tabelle emp im Workspace my_workspace_1:
In den Haupt-Workspace wechseln:
Dort ist die Tabelle in Ihrem Ursprungszustand zu sehen (ohne die 3 DML Änderungen)In welchem Workspace sind wir gerade?
Die Live Tabelle kann nun auf die Workspace Tabellen-Variante refreshed werden:
Oder die Workspace Variante wird auf Live synchronisiert:
Die Tabelle kann wieder aus der Versionsverwaltung herausgenommen werden durch:
Mit der Option FORCE wird das Kommando auch mit geänderten Workspacedaten durchgeführt, sonst erhält man einen Oracle Fehler:
Zum Löschen eines Workspace verwenden Sie:
Weitere Informationen zum Workspace Manager erhalten Sie in unserem PL/SQL II Kurs.
Installation von Oracle 23ai FREE auf Debian
Die folgende Installation wird zwar nicht von Oracle supported, aber das wird die 23ai FREE Edition sowieso nicht, also los geht´s …
Benutzer anlegen (kann man auch durch das Preinstall Skript durchführen lassen), aber hier ist man flexibler…
addgroup --system oinstall addgroup --system dba adduser --system --ingroup oinstall --shell /bin/bash oracle usermod -d /home/oracle oracle chown -R oracle:oinstall /home/oracle adduser -d /home/oracle oracle dba
Ein paar Packages vorinstallieren:
apt-get install alien rlwrap
REM Download der beiden Dateien von der URL: https://www.oracle.com/database/free/download/
Red Hat 8 / Rocky Linux 8 / Alma Linux 8 / Oracle Linux 8 wget https://yum.oracle.com/repo/OracleLinux/OL8/appstream/x86_64/getPackage/oracle-database-preinstall-23ai-1.0-2.el8.x86_64.rpm wget https://download.oracle.com/otn-pub/otn_software/db-free/oracle-database-free-23ai-1.0-1.el8.x86_64.rpm Red Hat 9 / Rocky Linux 9 / Alma Linux 9 / Oracle Linux 9 https://yum.oracle.com/repo/OracleLinux/OL8/appstream/x86_64/getPackage/oracle-database-preinstall-23ai-1.0-2.el9.x86_64.rpm wget https://download.oracle.com/otn-pub/otn_software/db-free/oracle-database-free-23ai-1.0-1.el9.x86_64.rpm
REM Unwandeln der .rpm Dateien in .deb Dateien:
alien --script oracle-database-preinstall*.rpm alien --script oracle-database-free-23ai*.rpm
### Achtung dauert laaaaange #### nicht abbrechen #### bei uns fast 1 Stunde ! zur Überbrückung bekommt man dauernd die Warnung: warning: oracle-database-free-23ai-1.0-1.el8.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID ad986da3: NOKEY oder wenn Sie Langeweile haben, können Sie die Größe des Zielordners "im Auge" behalten:
du -hs oracle-database-free-23ai-1.0
da sollten dann ca. 11 GB rauspurzeln
Sie können während Sie auf die Beendigung der Umwandlung warten schon mal (in einer zweiten Session) die .bash_profile Datei bearbeiten/anpassen:
cat << EOF > /home/oracle/.bash_profile export TERM=vt220 export EDITOR=vi export PS1="[\u@\h:\w]>" export DISPLAY=:0.0 export ORACLE_BASE=/opt/oracle export ORACLE_HOME=\$ORACLE_BASE/product/23ai/dbhomeFree export ORACLE_SID=FREE export ORACLE_INSTANCE=free export ORACLE_TERM=vt220 export ORA_NLS10=\$ORACLE_HOME/nls/data export LD_LIBRARY_PATH=\$LD_LIBRARY_PATH:\$ORACLE_HOME/lib export NLS_LANG=GERMAN_GERMANY.WE8MSWIN1252 export PATH=\$ORACLE_HOME/bin:\$PATH:/usr/sbin:/usr/ccs/bin alias cdo="cd \$ORACLE_HOME; pwd" alias cdd="cd \$ORACLE_BASE/oradata" alias cda="cd \$ORACLE_BASE/diag/rdbms/\$ORACLE_INSTANCE/\$ORACLE_SID/trace; pwd" alias cdn="cd \$ORACLE_HOME/network/admin; pwd" alias cde="cd \$ORACLE_BASE/admin/\$ORACLE_SID/dpdump" alias sp="\$ORACLE_HOME/bin/sqlplus '/ as sysdba'" alias l="ls -l" alias ll="ls -la" alias ipconfig="/sbin/ifconfig | grep Bcast" echo Folgende Einstellungen wurden gesetzt: env | grep ORA ps aux | grep [t]omcat | awk '{print "Tomcat-Prozess:" $2}' ps aux | grep [x]e_pmon | awk '{print "Oracle-Prozess:" $2}' ps aux | grep [t]ns | awk '{print "Listener-Prozess:" $2}' EOF
Wenn der Umwandlungsprozess fertig ist, geht es weiter mit:
apt update apt install libaio* apt install ./oracle-database-preinstall-23ai_1.0-1.5_amd64.deb apt install ./oracle-database-free-23ai_1.0-2_amd64.deb
dann geht es weiter mit:
Hinweis: Bei uns wurde bei der automatischen Installation der Listener Port 1539 verwendet und dann abgebrochen.
Sie können den Port in folgender Datei selber setzen:
vi /etc/sysconfig/oracle-free-23ai.conf LISTENER_PORT=1521
/etc/init.d/oracle-free-23ai configure
zweimal ein schönes langes Passwort eingeben, z.B. "dasistmeinPasswordganzschoenlangoder"
/etc/init.d/oracle-free-23ai configure Oracle Net Listener configured. Specify a password to be used for database accounts. Oracle recommends that the password entered should be at least 8 characters in length, contain at least 1 uppercase character, 1 lower case character and 1 digit [0-9]. Note that the same password will be used for SYS, SYSTEM and PDBADMIN accounts: Confirm the password: Configuring Oracle Listener. Listener configuration succeeded. Configuring Oracle Database FREE. Enter SYS user password: *** Enter SYSTEM user password: **** Enter PDBADMIN User Password: ***** Prepare for db operation 7% complete Copying database files 29% complete Creating and starting Oracle instance 30% complete 33% complete 36% complete 39% complete 43% complete Completing Database Creation 47% complete 49% complete 50% complete Creating Pluggable Databases 54% complete 71% complete Executing Post Configuration Actions 93% complete Running Custom Scripts 100% complete Database creation complete. For details check the logfiles at: /opt/oracle/cfgtoollogs/dbca/FREE. Database Information: Global Database Name:FREE System Identifier(SID):FREE Look at the log file "/opt/oracle/cfgtoollogs/dbca/FREE/FREE.log" for further details. Connect to Oracle Database using one of the connect strings: Pluggable database: pve4/FREEPDB1 Multitenant container database: pve4
Beim ersten Versuch gab es leider kein schöner Abschluss, wir bekommen den Fehler:
Listener configuration failed. Check log '/opt/oracle/cfgtoollogs/netca/netca_configure_out.log' for more details
und da steht drinnen:
The information provided for this listener is currently in use by other software on this computer.
In der listener.ora Datei ($ORACLE_HOME/network/admin) steht ein Port 1539 hmm, kenn ich nicht, Oracle verwendet normalerweise den Port 1521. Oder Sie haben wir oben beschrieben den Port bereits geändert, dann sollte alles durchlaufen.
So jetzt können Sie mit Ihren SQL / DBA /APEX Kenntnissen loslegen… oder doch erst einen Kurs bei uns besuchen ?Kein Problem, bei 44 verschiedenen Kursen ist sicher auch für Sie etwas dabei.
Wollten Sie immer schon mal zu Dokumentationszwecken ihre Shell Skripten in Oracle Tabellen speichern, das Ganze auch noch Clientseitig?
Das Problem sind die vielen Zeilenumbrüche in den Shell Skript Dateien, deswegen wandeln wir die Datei in BASE64 um. Da die Dateien länger als 32767 Zeichen lang werden können und damit die Maximallänge von VARCHAR2 in Tabellen von 4k (bzw. 32K ab 12.1 bei spezieller Einrichtung) übersteigen können,wandeln wir es sicherheitshalber in CLOB um.Leider hat Oracle eine solche Funktion nicht, dewegen schreiben wir sie uns selbst.
1. Funktion anlegen:
CREATE OR REPLACE FUNCTION Decode_Base64( p_base64 IN CLOB ) RETURN CLOB AS v_blob BLOB; v_decoded CLOB; v_length INT; v_warning INT; v_offset INT:= 1; v_context INT:= dbms_lob.default_lang_ctx; BEGIN -- Convert the Base64 CLOB into a BLOB DBMS_LOB.CREATETEMPORARY(v_blob, TRUE); DBMS_LOB.WRITE(v_blob, DBMS_LOB.GETLENGTH(p_base64), 1, UTL_RAW.CAST_TO_RAW(p_base64)); -- Decode the Base64 BLOB v_blob := UTL_ENCODE.BASE64_DECODE(v_blob); -- Determine the length of the decoded text v_length := DBMS_LOB.GETLENGTH(v_blob); -- Convert the BLOB to CLOB DBMS_LOB.CREATETEMPORARY(v_decoded, TRUE); DBMS_LOB.CONVERTTOCLOB( DEST_LOB => v_decoded, SRC_BLOB => v_blob, AMOUNT => v_length, DEST_OFFSET => v_offset, SRC_OFFSET => v_offset, blob_csid => dbms_lob.default_csid, lang_context => v_context, warning => v_warning ); -- Free resources DBMS_LOB.FREETEMPORARY(v_blob); RETURN v_decoded; END Decode_Base64; /
2. Ziel-Tabelle erstellen:
CREATE TABLE script_table ( id int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY, content CLOB);
3. Auf Shell-Ebene gewünschte Datei (hier: install.sh) in Base64 codieren und in Variable B64 speichern:
export B64=`echo -n \`cat install.sh\` | base64`
4. OS-Variable in Oracle Tabelle eintragen und wieder aus Base64 in CLOB Text konvertieren:
sqlplus scott/TIGER@172.24.114.237:1522/pdb1 <<EOF set echo off termout off DECLARE script_content CLOB := q'^${B64}^'; BEGIN INSERT INTO script_table(content)VALUES(decode_base64(script_content)); COMMIT; END; / EXIT; EOF
So nun steht Ihrer Versionsverwaltung oder dem Audit nichts mehr im Wege…Weitere tolle Tipps erhalten Sie in einem unserer 50 Oracle und Postgres Kurse. Wir freuen uns auf Sie …
Seit 30 Jahren warte ich auf dieses Feature, aber wie sagt man besser spät als nie …
Ab 23ai kann nun endlich ein Tablespace reorganisiert werden. Es gibt da nur ein paar Einschränkungen:
Zuerst prüfen wir mal, welche Tablespaces sich den lohnen bzgl eines Reorg?
set serveroutput on linesize 400 set long 9999999 WITH function analyze_tbs(tbs_name In VARCHAR2) RETURN CLOB IS PRAGMA AUTONOMOUS_TRANSACTION; v_result CLOB:=empty_clob(); BEGIN dbms_output.put_line('### '||tbs_name||' ###:'); DBMS_SPACE.TABLESPACE_SHRINK(tbs_name, SHRINK_MODE => DBMS_SPACE.TS_MODE_ANALYZE, SHRINK_RESULT => v_result); RETURN tbs_name||':'||chr(10)||v_result; END; select analyze_tbs(tablespace_name) from dba_tablespaces where bigfile='YES' and contents='PERMANENT';
Nun können wir einen Tablespace von Oracle shrinken/reorganisieren …
BEGIN DBMS_SPACE.TABLESPACE_SHRINK('SYSAUX', SHRINK_MODE => dbms_space.ts_mode_shrink, target_size => dbms_space.ts_target_max_shrink); END; /
Viel Spaß mit dem neuen gewonnen Speicherplatz. Die Einsparung kann man ja nun in eine Schulung stecken :-)
TomCat Version 10 ist nun einige Jahre auf dem Markt, nur leider unterstützt Oracle diese Version weiterhin nicht. Inwischen gibt es sogar auch schon TomCat 11!Wer doch schon mal auf undokumentierten Pfaden wandeln möchte, bekommt hier die Anleitung dazu.
Packen Sie nun die jakartaee-migration Dateien aus Schritt 3 z.B. in das Temp Verzeichnis aus (c:\temp für Windows oder /tmp für Linux)
Packen Sie auch die ORDS Version aus Schritt 4 im Temp Verzeichnis aus
Kopieren Sie die Datei ords.war in das Verzeichnis C:\Temp\jakartaee-migration-*\lib (Windows) oder /tmp/jakartaee-migration-*/lib (Linux)
Windows: "C:\Program Files\Java\jdk-17\bin\java.exe" -jar jakartaee-migration-1.0.8.jar ords.war ords_neu.war
Linux: java -jar jakartaee-migration-1.0.8.jar ords.war ords_neu.war
Nun wird die ords_neu.war in ords.war umbennant und in das webapps Verzeichnis des TomCat kopiert
Windows: move C:\Temp\jakartaee-migration-1.0.8\lib\ords_neu.war “C:\Program Files\Apache Software Foundation\Tomcat 10.1\webapps\ords.war” bzw. Version 11 Windows: move C:\Temp\jakartaee-migration-1.0.8\lib\ords_neu.war “C:\Program Files\Apache Software Foundation\Tomcat 11.0\webapps\ords.war”
Linux: mv /tmp/jakartaee-migration-1.0.8/lib/ords_neu.war /opt/tomcat/latest/webapss
Ords Einrichtung (Windows)
set JAVA_HOME="C:\Program Files\Java\jdk-17" set PATH=%PATH%;%JAVA_HOME% set ORDS_HOME=c:\oracle\ords set ORDS_CONFIG=c:\oracle\ords set ORDS_LOGS=%ORDS_CONFIG%\logs mkdir %ORDS_CONFIG% mkdir %ORDS_LOGS% dir %JAVA_HOME% set DB_PORT=1521 set DB_SERVICE=apex241 set SYSDBA_USER=SYS set SYSDBA_PASSWORD=sys set ORDS_PASSWORD=ords set ORA_HOST=172.30.30.2 #%ORDS_HOME%\bin\ords --config %ORDS_CONFIG% uninstall %ORDS_HOME%\bin\ords --config %ORDS_CONFIG% install ^ --log-folder %ORDS_LOGS% ^ --admin-user %SYSDBA_USER% ^ --db-hostname %ORA_HOST% ^ --db-port %DB_PORT% ^ --db-servicename %DB_SERVICE% ^ --feature-db-api true ^ --feature-rest-enabled-sql true ^ --feature-sdw true ^ --gateway-mode proxied ^ --gateway-user APEX_PUBLIC_USER ^ --proxy-user
ORDS Einrichtung (Linux)
export ORDS_HOME=/opt/oracle/ords mkdir -p $ORDS_HOME chown -R tomcat:dba $ORDS_HOME export ORA_HOST=172.30.30.2 export DB_SERVICE=apex241 export ORDS_CONFIG=/opt/oracle/ords cp ords.war $ORDS_HOME cp -R bin $ORDS_HOME cd $ORDS_HOME export SYSDBA_USER=sys export DB_PORT=1521 chmod u+x $ORDS_HOME/bin/ords tnsping $ORA_HOST:$DB_PORT/$DB_SERVICE lsnrctl status | grep $DB_SERVICE # Optional: Deinstallation # systemctl stop tomcat # $ORDS_HOME/bin/ords --config $ORDS_CONFIG uninstall --admin-user $SYSDBA_USER $ORDS_HOME/bin/ords --config $ORDS_CONFIG install \ --log-folder $ORDS_HOME \ --admin-user $SYSDBA_USER \ --db-hostname $ORA_HOST \ --db-port $DB_PORT \ --db-servicename $DB_SERVICE \ --feature-db-api true \ --feature-rest-enabled-sql true \ --feature-sdw true \ --gateway-mode proxied \ --gateway-user APEX_PUBLIC_USER \ --proxy-user
Auf jeden Fall immer beachten: Der TomCat muss wissen, wo sein Configfile für den ORDS ist.
Unter Windows trägt man das im Apache Tomcat Config Fenster im Bereich Java ein:
-Dconfig.url=C:\oracle\ords
Unter Unix natürlich entsprechend (Datei /etc/systemd/system/tomcat.service):
Environment="JAVA_OPTS=-Djava.security.egd=file:///dev/urandom -Dconfig.url=/opt/oracle/ords"
Danach sollte in der der Catalina*.log etwas stehen wie:
19-May-2025 11:06:32.611 INFORMATION [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.home=C:\Program Files\Apache Software Foundation\Tomcat 9.0 19-May-2025 11:06:32.611 INFORMATION [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dcatalina.base=C:\Program Files\Apache Software Foundation\Tomcat 9.0 19-May-2025 11:06:32.611 INFORMATION [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.io.tmpdir=C:\Program Files\Apache Software Foundation\Tomcat 9.0\temp 19-May-2025 11:06:32.611 INFORMATION [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.manager=org.apache.juli.ClassLoaderLogManager 19-May-2025 11:06:32.611 INFORMATION [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Djava.util.logging.config.file=C:\Program Files\Apache Software Foundation\Tomcat 9.0\conf\logging.properties 19-May-2025 11:06:32.611 INFORMATION [main] org.apache.catalina.startup.VersionLoggerListener.log Command line argument: -Dconfig.url=C:\opt\oracle\ords
So, das war es schon. nur immer daran denken, wenn es ein Problem in dieser nicht unterstützen Konfiguartion gibt, müsste das Ganze erst unter TomCat Version 9 reproduziert werden!
Viel Spass und bis Bald in einem unserer APEX Kurse …
Have you always wanted to save your shell scripts in Oracle tables for documentation purposes, even on the client side?
The problem is the many line breaks in the shell script files, so we convert the file to BASE64. Since the files can be longer than 32767 characters and thus exceed the maximum length of VARCHAR2 in tables of 4k (or 32K from 12.1 with special setup),
1. Create Funktion :
2. Target-Tabelle:
3. At shell level, code the desired file (here: install.sh) in Base64 and save it in variable B64:
4. Enter OS variable in Oracle table and convert back from Base64 to CLOB text:
So now nothing stands in the way of your version management or audit...You can get more great tips in one of our 50 Oracle and Postgres courses. We look forward to seeing you ...
I've been waiting 30 years for this feature, but as they say – better late than never…
Starting with Oracle 23ai, it is finally possible to reorganize a tablespace. There are just a few limitations:
It must be a Bigfile Tablespace
It must not contain any exotic or read-only objects such asAUD$UNIFIED
AUD$UNIFIED
First, let's check which tablespaces are actually worth reorganizing.
Now, we are finally able to shrink or reorganize a tablespace in Oracle...
Have fun with the newly reclaimed space. The savings can now be invested in a training course. :-)
The question of how to display a PDF in a page comes up very often in our APEX courses. In our case, the PDF comes from a table in the Oracle database.
Preparation:
CREATE TABLE emp_lob ( EMPNO NUMBER(4,0), ENAME VARCHAR2(10 BYTE), DATEINAME VARCHAR2(512 BYTE), BESCHREIBUNG VARCHAR2(4000 BYTE), DATEITYP VARCHAR2(100 BYTE), L_UPDATE DATE, BILD BLOB)
Create an application process (Shared Components / Application Logic / Application Process) in APEX: Name getPDF and define as Ajax Processes
The process has the following code:
begin for file in (select * from emp_lob where empno = :EMPNO and dateityp='application/pdf') loop sys.htp.init; sys.owa_util.mime_header( file.dateityp, FALSE ); sys.htp.p('Content-length: ' || sys.dbms_lob.getlength( file.bild)); sys.htp.p('Content-Disposition: inline; filename="' || file.fname || '"' ); sys.htp.p('Cache-Control: max-age=3600'); -- tell the browser to cache for one hour, adjust as necessary sys.owa_util.http_header_close; sys.wpg_docload.download_file( file.bild ); apex_application.stop_apex_engine; end loop; end;
<object data="http://127.0.0.1:8080/ords/f?p=100:0:&SESSION.:APPLICATION_PROCESS=getPDF:::EMPNO:&P1_EMPNO." style="width:100%;height:700px"> <a href="http://127.0.0.1:8080/ords/f?p=100:0:&SESSION.:APPLICATION_PROCESS=getPDF:::EMPNO:&P1_EMPNO.">PDF laden</a> </object>
And now have fun displaying all your PDFs. We use it to display our PDF invoices in APEX :-)See you (hopefully) soon in one of our courses ...
In our training sessions, we frequently get interesting questions about the Interactive Grid. Here's a small selection:
Requirements:
There is a grid on the Scott.emp table with the static ID EMP
There is a select list named P1_JOB
var model = apex.region("EMP").widget().interactiveGrid("getViews", "grid").model; model.forEach(function(r) { model.setValue(r, "JOB", $v("P1_JOB" )); // Setzen des Jobs pro Zeile })
2. Only the entries selected using the checkbox (column 1) in the grid should be updated.
var grid = apex.region("EMP").widget().interactiveGrid("getViews","grid"); var model = grid.model; var selectedRecords = grid.getSelectedRecords(); //console.log("Records" +selectedRecords.length); for (idx = 0; idx < selectedRecords.length; idx++) { record = model.getRecord(selectedRecords[idx][0]); model.setValue(record, "JOB", $v( "P1_JOB" )); //console.log(idx+ " " + selectedRecords[idx][1] ); //Felder [1] EMPNO [2] ENAME, [3] JOB ... }
3. ou want to handle writing back to the database yourself? No problem. Simply replace the process with:
IF :APEX$ROW_STATUS='C' THEN INSERT INTO emp (empno,ename,job,mgr,hiredate,sal,comm,deptno) VALUES (:EMPNO,:ENAME,:JOB,:MGR,:HIREDATE,:SAL,:COMM,:DEPTNO); ELSIF :APEX$ROW_STATUS='U' THEN UPDATE emp SET ename=:ENAME,job=:JOB, mgr=:MGR,hiredate=:HIREDATE ,sal=:SAL,comm=:COMM, deptno=:DEPTNO WHERE empno=:EMPNO ; ELSIF :APEX$ROW_STATUS='D' THEN DELETE FROM emp WHERE empno=:EMPNO; END IF;
That was a small excerpt from the many questions we get in our APEX courses. Do you have questions too? Then join one of our courses… we look forward to seeing you!
In today's tip, we will look at a few practical examples of regular expressions in Oracle.
Example 1: Credit card numbers usually have the format: 1234-1234-1234-1234We look for two blocks of 4 in a string with numbers and a minus in between and replace each block with: xxxx-xxxx:
select regexp_replace( '1234-5678-1111-2222', '[[:digit:]]{4}-[[:digit:]]{4}','xxxx-xxxx') from dual;
Result: xxxx-xxxx-xxxx-xxxx
Or we look for four blocks of 4 with numbers and replace this with: XXXX:
select regexp_replace( '1234-5678-1111-2222', '[[:digit:]]{4}','xxxx') from dual;
Only the last block of 4 is to be issued:
select regexp_replace( '1234-5678-1111-2222', '([[:digit:]]{4})(-)([[:digit:]]{4})(-)([[:digit:]]{4})(-)([[:digit:]]{4})','XXXX-XXXX-XXXX-\7') from dual;
Result:
XXXX-XXXX-XXXX-2222
Alternatively, instead of [[:digit:]] with \d replace
select regexp_replace( '1234-5678-1111-2222', '\d{4}','x') from dual;
Result: x-x-x-x
Beispiel 2: Wir löschen einige HTML Tags in einem String:
select regexp_replace( '<div>Hallo</div><strong> Kurs</strong>', '(<\/?div>|<\/?p>|<\/?strong>)','') from dual;
or we delete all HTML tags in the string
select regexp_replace( '<div>Hallo</div><strong> Training</strong>', '<\/?[^>]*>,'') from dual;
This was a small selection of examples, which we are constantly expanding. Or you can come to the PL/SQL or PL/SQL II course, for example, where these topics are also discussed in detail.
Starting with Oracle version 21c, in addition to the alert.log, a new file is delivered: the Attention.log. This file is intended to contain important information as a summary of the alert.log.
Well, I hope this gets improved a bit, but still, it would be useful to read the file using a SELECT statement. I was hoping someone had already done the work (Google, where are you when you need it...), but unfortunately, I found nothing.
Okay, then I’ll do it myself…
We give the objects to the SYSTEM user, but of course, you can also create another user for this purpose.
ALTER SESSION SET current_schema=system; col adir new_value adir col afile new_value afile with diag as (select sys_context('userenv','PLATFORM_SLASH') as ps,value from v$diag_info where name='Attention Log') select substr(value,1,instr(value,ps,-1)-1) as adir, substr(value,instr(value,ps,-1)+1) as afile from diag;
CREATE OR REPLACE DIRECTORY attention_dir as '&adir.'; GRANT READ ON DIRECTORY attention_dir to system;
CREATE OR REPLACE TYPE attention_type AS OBJECT ( NOTIFICATION VARCHAR2(4000), ERROR VARCHAR2(4000), URGENCY VARCHAR2(4000), INFO VARCHAR2(4000), CAUSE VARCHAR2(4000), ACTION VARCHAR2(4000), CLASS VARCHAR2(4000), TIME TIMESTAMP WITH TIME ZONE ); /
CREATE OR REPLACE TYPE attention_tab_type AS TABLE OF attention_type; /
CREATE OR REPLACE FUNCTION read_attention_log RETURN attention_tab_type PIPELINED IS f_handle utl_file.file_type:=utl_file.fopen( location=>'ATTENTION_DIR', filename=>'&afile.', open_mode=>'r', max_linesize=>32767); text varchar2(32767); v_a_log attention_type:=attention_type(null,null,null,null,null,null,null,null); v_i INT:=1; BEGIN LOOP BEGIN utl_file.get_line(f_handle,text); -- Neue Zeile lesen IF substr(text,1,16)=' "NOTIFICATION"' THEN v_a_log.NOTIFICATION:=rtrim(rtrim(substr(text,21),','),'"'); END IF; IF substr(text,1,9)=' "ERROR"' THEN v_a_log.ERROR:=rtrim(rtrim(substr(text,21),','),'"'); END IF; IF substr(text,1,11)=' "URGENCY"' THEN v_a_log.URGENCY:=rtrim(rtrim(substr(text,21),','),'"'); END IF; IF substr(text,1,8)=' "INFO"' THEN v_a_log.INFO:=rtrim(rtrim(substr(text,21),','),'"'); END IF; IF substr(text,1,9)=' "CAUSE"' THEN v_a_log.CAUSE:=rtrim(rtrim(substr(text,21),','),'"'); END IF; IF substr(text,1,10)=' "ACTION"' THEN v_a_log.ACTION:=rtrim(rtrim(substr(text,21),','),'"'); END IF; IF substr(text,1,9)=' "CLASS"' THEN v_a_log.CLASS:=rtrim(rtrim(substr(text,21),','),'"'); END IF; IF substr(text,1,8)=' "TIME"' THEN v_a_log.TIME:=to_timestamp_tz(rtrim(substr(text,21),'"'),'YYYY-MM-DD"T"HH24:MI:SS.FFTZH:TZM'); PIPE ROW (v_a_log); v_a_log :=attention_type(null,null,null,null,null,null,null,null); END IF; EXCEPTION WHEN NO_DATA_FOUND THEN EXIT; -- Keine Zeile im Attention.log mehr gefunden oder Fehler=> Schleife verlassen WHEN OTHERS THEN RAISE; END; END LOOP; utl_file.fclose(f_handle); END; /
And now you can read the attention.log via SQL...
SELECT * FROM table(read_attention_log);
Installation of Oracle 23ai FREE on Debian
The following installation is not supported by Oracle, but since the 23ai FREE Edition won’t be supported anyway, let's get started...
Create a user (can also be done through the preinstall script), but here you have more flexibility...
Preinstall a few packages:
REM Download the two files from the URL: https://www.oracle.com/database/free/download/
REM Convert the .rpm files to .deb files:
Attention, it takes a looooong time #### do not interrupt ####It took almost 1 hour for us!During this time, you will constantly get the warning:warning: oracle-database-free-23ai-1.0-1.el8.x86_64.rpm: Header V3 RSA/SHA256 Signature, key ID ad986da3: NOKEYOr, if you're bored, you can keep an eye on the size of the target folder:
There should be about 11 GB as a result.
While waiting for the conversion to finish, you can already (in a second session) edit/adjust the .bash_profile file:
When the conversion process is complete, proceed with:
Then continue with:
Note: During the automatic installation, the listener port 1539 was used and then the process was interrupted.
You can set the port yourself in the following file:
Enter a nice long password twice, for example, "SuperSecretPassword123!WithUnicornAndPizza!"
On the first attempt, there was unfortunately no successful completion, and we received the error:
Listener configuration failed. Check log '/opt/oracle/cfgtoollogs/netca/netca_configure_out.log' for more details.
And it says inside:
In the listener.ora file ($ORACLE_HOME/network/admin), there is a port 1539, hmm, I don't recognize that, Oracle usually uses port 1521.Or, as described above, you may have already changed the port, in which case everything should work fine.
Now, you can start using your SQL / DBA / APEX skills... or maybe first take a course with us?No problem, with 44 different courses, there is certainly something for you!
Today's tip is dedicated to the most important concept of a database: the table!
Since I keep having to search for examples of special CREATE TABLE commands for Oracle databases, it was time to create my own summary.
Case 1: A table is to be created with the most common numeric data types:
Case 2: Next, we take the text and other data types:
Case 3: The table is to be created with the new LOB storage technology (from 11.1), the secure files:
Case 4: The table should only be physically created once the first line has been entered:
Case 5: The table is to be created with the NOLOGGING attribute:
The table can subsequently be changed back to LOGGING or NOLOGGING:
Case 6: You want to specify a special tablespace for the table:
Case 7: The table should have a primary key:
Case 8: The table should have a foreign key:
Case 9: The table should have a special sorting for a column. This function is only available from 12.2 onwards. In addition, the parameter max_string_size= EXTENDED must be set.
Case 10: The table should only store the data temporarily (until the end of the session):
Case 11: The table should only store the data temporarily (until the end of the transaction):
Case 12: From version 18, a temporary table can be created which is deleted at the end of the transaction together with its definition.Note: It must have a prefix (ora$ptt) in the name. However, this can be changed via the initialization parameter PRIVATE_TEMP_TABLE_PREFIX.
Case 13: Also only available from version 18, this is the second variant of the private temporary table, which is only deleted at the end of the session:
Case 14: The table should remember the change SCN per line and not just per block:
Case 15: The table is to be based on a file that is outside the database:
Als Benutzer mit DBA Rechten ausführen:
do it as SCOTT User:
Case 16: Blockchain table (only from version 21c)
Case 17: Interval range partitioned table (1 month interval)
Case 18: Interval Range-Partitioned Table (1 day interval)
Case 19: Interval Range-Partitioned Table (1 year interval)
Case 20: Range partitioning with own interval