<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