<Insert Picture Here>
Anwendungsentwicklung auf RAC und Data Guard
Sebastian Solbach, ORACLE Deutschland B.V. Co. KG
Agenda
HA in der Anwendungsentwicklung ?
Basis Setup (Datenbank)
Transaction Guard (OCI/ODP.NET/JDBC)
Application Continuity (nur JDBC)
Best Practices
Diverses
Maximum Application Availability (MAA2)
Mehr als 1 Problem
Datenbank Ausfall konfrontiert Entwickler mit 5 Problemen:
1. Ausfall festestellen
2. Wiederaufnahme im vorgegebenen Zeitfenster
3. Exception Handling
4. Transaktionsstatus herausfinden
5. Weiterführung der aktuellen Transaktion
Das Problem: “In-Flight” Work
Pre-12c Situation
Netzwerk / Datenbank Ausfall führt zu
einem ungewissen Transaktionsstatus
– Neustart der Mid-Tier
– Frustration der Benutzer
– Abgebrochene Arbeit
– Doppelte Buchungen
– Entwicklungsaufwand
Pre-12c Situation
HA Mechanismen und Einschränkungen
Ausfall
‒ Fast Application Notification (FAN) / Fast Connection Failover
Recovery Zeitfenster? Abhängig von Ausfallzenario und Technologie
Exception Handling? Fehler & Reaktionen nicht vollständig formalisiert
Aktuelle Transaktion? Ungewiss…
Weiterführen aktueller Transaktion? Nicht verfügbar!
Ausfall feststellen: Fast Application Notification
Applikationen verlieren Zeit
FAN & FCF
• Warten auf TCP/IP Timeouts
Down – Service/Knoten down
<50ms für Failover
• Fehler bei geplanten Ausfällen
• Verbindungsabbrüche bei
Nichtverfügbarkeit des Services
• Keine Neu-Verbindungsversuche
bei Serviceverfügbarkeit
• Verbindungen auf überlastete
Knoten
Planned Down – Entleerung des
Connectionspools ohne
Verbindungsabbrüche
Up – Verteilung der Arbeitslast bei
Serviceverfügbarkeit
RLB % - Informationen zur
optimalen Verteilung
Affinity – Optimierung
Workload lokal zu halten
Alle 12c
Treiber
verwenden
FAN über
ONS
Fast Application Notification: Wo?
Client
10g
11g
12c
JDBC Implicit Connection Cache
ONS
ONS
deprecated
ONS
ONS
AQ
ONS
JDBC Universal Connection Pool
ODP.NET Unmanaged OCI)
AQ
ODP.NET Managed (C#)
OCI Session Pool
ONS
AQ
ONS
WebLogic Active GridLink
ONS
ONS
Tuxedo
ONS
ONS
JDBC thin standalone
ONS
ONS
AQ
ONS
OCI/OCCI driver
AQ
AQ
12c JDBC FAN Konfiguration
Prüfen, ob ons.jar im Classpath enthalten ist
Registrierung bei den ONS daemons
–
ods.setConnectionCachingEnabled(True);
–
ods.setFastConnectionFailoverEnabled(true);
Wichtig: SCAN Loadbalancing aktivieren
–
oracle.jdbc.thinForceDNSLoadBalancing=true
Default: ONS verwendet 3 End-points. Bei Data Guard dies erhöhen:
–
oracle.ons.maxconnections=4 (or more)
Notwendig vor 12c:
–
ods.setONSConfiguration("nodes=bumucsvm1:6200,bumucsvm2:6200,
bumucsvm3:6200,bumucsvm4:6200");
12c OCI FAN Konfiguration
12c OCI Clients
Verwenden von oraaccess.xml
Pre-12c OCI Clients
<oraaccess>
<default_parameters>
<events>true</events>
</default_parameters>
</oraaccess>
– Aktivierung der OCI_EVENTS während der Luafzeit im Client
(OCIEnvCreate(...) )
– Linken der Applikation mit der Client Thread O/S library.
Service Konfiguration für die AQ HA Notification:
srvctl modify service -db EM -service GOLD -notification TRUE
Falls die Session nicht in den Pool zurückgegeben werden:
Check OCI_ATTR_SERVER_STATUS
12c ODP.NET FAN Konfiguration
Aktivierung von HA Events durch "HA Events=true“ und "pooling=true" im
Connection String
"user id=oracle; password=oracle; data source=HA; pooling=true; HA events=true;“
"Load Balancing=true" zur Verwendung von Runtime Conntection LB.
user id=oracle; password=oracle; data source=HA; HA events=true; load balancing=true;
Falls die Session nicht in den ODP.NET zurückgegeben werden:
Check Connection.State (6620732)
Pre-12c SRVCTL für die Event Notification (wie bei OCI)
Wie funktioniert FAN?
Beispiel: Geplante Wartungsarbeiten RAC (z.B. PSU DB Patch):
DBA „schwenkt“ Service von einem Knoten auf den anderen (ohne
Force!):
srvctl relocate service -db .. -service .. -oldinst .. -newinst ..
– Connection Pool baut offene Sessions ab, sobald diese inaktiv im Pool
sind. Neue Connections werden auf den neuen Knoten geöffnet
Nach ca. 15 Minuten werden die verbleibenden Sessions Transaktional
geschlossen
exec dbms_service.disconnect_session('service_name‚DBMS_SERVICE.POST_TRANSACTION);
Datenbanklösungen für MAA
Real Application Cluster
– Automatische Fehlererkennung in <30 Sekunden
– Schnelles konfigurierbares Instanz Recovery
– Geplante Übernahme ohne Downtime
RAC One Node
– Automatische Fehlererkennung in <30 Sekunden
– Neustart der Datenbank & Instanz Recovery
– Geplante Übernahme ohne Downtime
Active Data Guard / Data Guard
– (Automatische) Fehlererkennung in <2 Minuten
– Neustart der Datenbank in Desaster Recovery Entfernung
– Geplante Übernahme mit Downtime
Hochverfügbarkeit
Interim, One- off
PSU/CPU
Bundle Patch
Patch Set
RAC Rolling
96%*
All
Almost always
No
Standby First
98%
All
All
No
Out of Place
All
All
Exadata bundles
No
Online - Hot
82%*
No
No
No
Exception Handling? “Recoverable Error”
Formalisiert:
– OracleException.IsRecoverable property
– JDBC throws SQLRecoverableException
Applikationen brauchen keine eigene Liste mit Fehlercodes (z.B.,
ORA-1033, ORA-1034, ORA-xxx)
Lösungen für Transaktionsstatus & Fortführung
Neu in Oracle Database 12c
Transaction Guard
Application Continuity
Verlässliches Protokoll und
API den Status der letzten
Transaktionen zu überprüfen
Automatische Wiederholung
(Replay) der Benutzertransaktion nach einem
Ausfall oder während einer
Wartung
Agenda
HA in der Anwendungsentwicklung ?
Basis Setup (Datenbank)
Transaction Guard (OCI/ODP.NET/JDBC)
Application Continuity (nur JDBC)
Best Practices
Diverses
Verwenden eines eigenen Services !!!
... und das gilt nicht nur für RAC, Data Guard und Multitenant (PDB)
Oracle Datenbank 12c & Oracle Client 12c
srvctl modify service -db ORCL -service APPCON
-failovertype TRANSACTION -replay_init_time 300
-failoverretry 30 -failoverdelay 3
-notification TRUE -commit_outcome TRUE
Services in der Datenbank:
https://apex.oracle.com/pls/apex/GERMAN_COMMUNITIES.
SHOW_TIPP?P_ID=741
Service Konfiguration Transaction Guard
COMMIT_OUTCOME
– Werte : TRUE oder FALSE, Default: FALSE
– Greift sofort bei neuen Sessions
RETENTION_TIMEOUT
– Einheit: Sekunden, Default: 24 Stunden (86400)
– Maximalwert: 30 Tage (2592000)
AQ_HA_NOTIFICATIONS
– Werte: TRUE oder FALSE, Default: FALSE (noch)
– Auf TRUE setzen für FAN !!
Service Konfiguration Application Continuity
Zusätzlich für Application Continuity
FAILOVER_TYPE
– Werte : NONE, SESSION, SELECT, TRANSACTION, Default: NONE
– Für AC auf TRANSACTION setzen
REPLAY_INITIATION_TIMEOUT = 300
– Zeit in Sekunden nach der ein Replay abgebrochen wird
FAILOVER_RETRIES = 60
– Anzahl der Verbindungsversuche für einen Replay
FAILOVER_DELAY = 3
– Verzögerung in Sekunden zwischen den Verbindungsversuchen
Rechte & Datenbank Parameter
Applikationsbenutzer braucht Rechte auf das DBMS_APP_CONT
Package
GRANT EXECUTE ON DBMS_APP_CONT TO <app-name>;
REMOTE_LISTENERS muss alle Listener kennen, über die die Clients
sich initial verbinden (im Normalfall nur SCAN)
alter system set
REMOTE_LISTENERS='SCAN.domain.com:1521'
Agenda
HA in der Anwendungsentwicklung ?
Basis Setup (Datenbank)
Transaction Guard (OCI/ODP.NET/JDBC)
Application Continuity (nur JDBC)
Best Practices
Diverses
Transaction Guard
Verlässliche Information über eine
Transaktion nach einem Ausfall
Mit Hilfe von Transaction Guard kann die
Applikation auf alle Fehler richtig reagieren
Verhindert “Logische Korruptionen” druch
Wiederholung
Application Continuity verwendet
Transaction Guard
Transaction Guard ist verfügbar mit JDBCthin, OCI/OCCI, ODP.NET
Die Einheit: “Datenbank Request”
Legt die Grenzen für die Wiederholung fest
Begin
Request
PoolDataSource pds = GetPoolDataSource();
Connection conn = getConnection(pds);
PreparedStatement pstmt = …
…
SQL, PL/SQL, local calls, RPC
…
conn.commit();
conn.close();
Request Body
schließt
gewöhnlich mit
COMMIT ab
End
Request
Herausforderung: Commit Ergebnis
Unterbrechung der Kommunikation während eines COMMIT
Java/JDBC Applikation bekommt eine Fehlermeldung :”Failed”
– Keine Information über das Ergebnis dieser “in-flight” Transaktion
Typisches Szenario
– t0: Applikation prüft Status der Transaktion und erhält “Not COMMITTED”.
Auf Basis dieser Information wird das weitere Vorgehen bestimmt
– t1: Transaktion wird doch noch abgeschlossen
– Es gibt (bis 12c) keinen verlässliche Möglichkeit den Status einer in-flight
Transaktion zu prüfen
Transaction Guard – Schematische Darstellung
Applikation/Treiber - RDBMS Interaktion
Transaction Guard
Verlässliche Information des COMMIT Ergebnisses
1.
RDBMS assoziiert zu jeder “in-flight” Transaktion eine logische
TransaktionsID (LTXID)
LTXID wechselt NUR bei einem erfolgreichen COMMIT oder ROLLBACK
2.
3.
LTXID wird z.B. an JDBC kommuniziert
Falls die Verbindung abbricht
LogicalTransactionId ltxid = oldConn.getLogicalTransactionId();
OracleConnection newConn = getConnection();
CallableStatement cstmt = newConn.prepareCall(GET_LTXID_OUTCOME);
RDBMS: Falls GET_LTXID_OUTCOME weder Committed noch Rollback
zurückgibt, wird die Transaktion daran gehindert zu COMMITTEN
Commit Outcome
GET_COMMIT_OUTCOME forciert das Commit Ergebnis der Session:
COMMITTED
– TRUE the user call executed at least one commit
– FALSE the user call is uncommitted and stays that way
USER_CALL_COMPLETED
– TRUE the user call ran to completion.
– FALSE the user call is not known to have finished
e.g. autocommit results or from PL/SQL, out binds may be missing
Ein Beispiel
Datenbank Sessions brechen ab:
–
–
FAN & FCF schliessen tote Sessions (sehr schnell!)
Applikation bekommt einen Fehler
Wenn “recoverable error” dann
–
–
–
Get last LTXID von der toten Session
Anfordern einer neuen Datenbank Session
Forcieren des Commit Ergebnisses:
DBMS_APP_CONT.GET_LTXID_OUTCOME with last LTXID
If committed then {
process committed;
if user_call_completed then application may continue
else application may not be able to continue}
Else process uncommitted
Transaction Guard
Best Practices
Transaction Guard nur verwenden, wenn die Session tot ist oder nicht
reagiert:
DO NOT get the LTXID and hold onto it at runtime.
DO NOT use GET_LTXID_OUTCOME on yourself.
DO NOT use GET_LTXID_OUTCOME with an LTXID from a different
environment.
DO use GET_LTXID_OUTCOME against a session that receives a
recoverable error or timeout.
Transaction Guard
Treiber Unterstützung mit 12.1.0.1
Supportete Commit Modelle
‒
‒
‒
‒
‒
Local TXN
Auto-commit, Commit on Success
Commit embedded in PL/SQL
DDL, DCL, Parallel DDL
Remote, Distributed
Ausgeschlossen
XA in 12.1
‒ R/W DBLinks von Active Data Guard / Read Only
‒
Agenda
HA in der Anwendungsentwicklung ?
Basis Setup (Datenbank)
Transaction Guard (OCI/ODP.NET/JDBC)
Application Continuity (nur JDBC)
Best Practices
Diverses
Application Continuity
Maskiert ungeplante und geplante Ausfälle
“In-flight” Prozess läuft weiter
Wiederholt “in-flight” Prozess nach einem
Recoverable Error
Verbirgt viele Hardware, Software, Netzwerk,
Storage Fehler und Ausfälle
Unterstützt JDBC-Thin, UCP, WebLogic
Server und 3rd Party Java Applikationen
Oracle RAC, RAC One, & Active Data Guard
Phasen bei Application Continuity
1-Laufzeit Operationen
2-Reconnect
3-Replay
• Überwachung der
einzelnen Datenbank
Requests
• Prüft ob für den Request
Replay aktiviert wurde
• Wiederholung der
gespeicherten Aufrufe
• Verwaltung von Timeouts
• Ermittlung was / was nicht
wiederholt werden kann
• Eröffnet neue Verbindung
• Verifizierung der
Ergebnisse mit den
Vorhergehenden.
• Speichert den orginären
Aufruf inkl. Bind Variablen
und Validierung
• Validiert die
Zieldatenbank/Zielinstanz
• Verwendet Transaction
Guard zur Ermittlung des
COMMIT Ergebnisses
• Führt den Request
weiter, falls die
Wiederholung
erfolgreich ist
Konfiguration Application Continuity
JDBC / WLS
JDBC URL oder Property Datei
# Verwendung der neuen 12.1 Replay DataSource
datasource=oracle.jdbc.replay.OracleDataSourceImpl
WebLogic Console oder UCP/Weblogic Property Datei
# Auswählen der neuen 12.1
replay datasource=oracle.jdbc.replay.OracleDataSourceImpl
Setzen von ONS nicht mehr notwendig, da in 12c die ONS Server
automatisch konfiguriert werden (via. Listener)
Verwenden des Services in JDBC
Oracle Client 12c
jdbc:oracle:thin:@(DESCRIPTION =
(TRANSPORT_CONNECT_TIMEOUT=3)(CONNECT_TIMEOUT=5)
(RETRY_COUNT=3)(FAILOVER=ON)(ADDRESS=
(PROTOCOL=tcp)(HOST=SCAN.domain.com)(PORT=1521))
(CONNECT_DATA=(SERVICE_NAME=APPCON))
Ausnahmen: Replay deaktiviert
Global
• Default Datenbank
Service oder Default PDB
Service
• XA in 12.1
• Verwendung einiger
JDBC-Klassen aus dem
Package oracle.sql
Request
• Eigentlich logisch
(restricted calls):
– Alter System
– Alter Database
• Active Data Guard mit
read/write Datenbanklinks
Target Database
• Nicht verfügbar bei
– Logical Standby
– Golden Gate
Restriktionen: Wann wird nicht wiederholt?
Normal Runtime
Reconnect
Aufrufe im selben Request nach
• Fehler ist nicht “recoverable”
• Einem erfolgreichen Commit
im dynamischen Modus
• Fehler beim erneuten
Verbindungsaufbau
• Auftreten eines “restricted
call”
•Zieldatenbank nicht für Replay
geeignet
• disableReplay API
• Letzter Aufruf erfolgreich
committed im dynamischen
Modus
Replay
•Validierung erkennt
Unterschied im Ergebnis
Agenda
HA in der Anwendungsentwicklung ?
Basis Setup (Datenbank)
Transaction Guard (OCI/ODP.NET/JDBC)
Application Continuity (nur JDBC)
Best Practices
Diverses
Deaktiveren von Replay ?
Verwenden der disableReplay() API für Aufrufe, die nicht wiederholt
werden sollen/dürfen, insbesondere für Externe Aktionen:
– Autonome Transaktionen
– UTL_HTTP, UTL_URL
– UTL_FILE, UTL_FILE_TRANSFER
– UTL_SMPT, UTL_TCP
– UTL_MAIL
– DBMS_PIPE (nicht empfohlen bei RAC)
– DBMS_ALERT (Ebenfalls Vorsicht bei RAC: Community Tipp)
https://apex.oracle.com/pls/apex/
GERMAN_COMMUNITIES.SHOW_TIPP?P_ID=1621
Optinale Datenbank Konfiguration
„Mutables“ Rechte vergeben
Damit z.B. Sysdate bei einem Replay denselben Wert zurückgibt:
GRANT [KEEP DATE TIME | KEEP SYSGUID].. [to USER]
REVOKE [KEEP DATE TIME | KEEP SYSGUID][from USER]
GRANT KEEP SEQUENCE.. [to USER] on [sequence object];
REVOKE KEEP SEQUENCE [from USER] on [sequence object];
ALTER SEQUENCE.. [sequence object] [KEEP|NOKEEP];
CREATE SEQUENCE.. [sequence object] [KEEP|NOKEEP];
Agenda
HA in der Anwendungsentwicklung ?
Basis Setup (Datenbank)
Transaction Guard (OCI/ODP.NET/JDBC)
Application Continuity (nur JDBC)
Best Practices
Diverses
Kill Session
Was passiert, wenn der DBA eine Session killt?
Natürlich greift AC...
– ... nicht unbedingt immer gewollt!
SQL> alter system kill session 'sid, serial#, @inst' noreplay;
SQL> alter system disconnect session 'sid, serial#, @inst'
noreplay;
SQL> execute DBMS_SERVICE.DISCONNECT_SESSION(‘[service name]’,
DBMS_SERVICE.NOREPLAY) ;
Lizenzen für produktiven Einsatz
Transaction Guard: Enterprise Edition
Application Continuity: RAC oder Active Data Guard Option
Oracle® Database Licensing Information 12c Release 1 (12.1)
http://docs.oracle.com/cd/E16655_01/license.121/e176
14/editions.htm#DBLIC116
Links & weitere Informationen
DBA Community
https://blogs.oracle.com/dbacommunity_deutsch/
OTN
http://www.oracle.com/technetwork/products/clustering/ac-overview-1967264.html
Whitepapers
http://www.oracle.com/technetwork/database/database-cloud/private/transaction-guardwp-12c-1966209.pdf
http://www.oracle.com/technetwork/database/database-cloud/private/applicationcontinuity-wp-12c-1966213.pdf
Dokumentation
http://docs.oracle.com/cd/E16655_01/java.121/e17659/app_cont.htm#JJUCP8254