# Failback DR → PRIMARY (procedura inversă) Procedura de revenire de pe serverul DR (VM 109, `10.0.20.37`) pe serverul de producție reparat sau reinstalat (PRIMARY, `10.0.20.36`). > **Context**: Această procedură se aplică DUPĂ ce DR a preluat producția (vezi `README.md` § "Emergency DR Activation"). Aplicațiile rulează pe DR (`10.0.20.37:1521/ROA`), PRIMARY a fost reparat sau reinstalat de la zero, și acum trebuie mutată producția înapoi pe PRIMARY. --- ## ⚠️ ATENȚIE: Pe PRIMARY instalează Oracle **19c** (recomandat ferm pentru failback) Backup-urile RMAN existente sunt luate din Oracle **19.3** (`ORACLE_HOME = WINDOWS.X64_193000_db_home`, `compatible=19.0.0`). **Instalează Oracle Database 19c:** - Versiune: **Oracle Database 19c** (19.3 base + ultimul Release Update) - Edition: aceeași cu cea originală — verifică pe DR cu `SELECT banner FROM v$version;` - Installer: `WINDOWS.X64_193000_db_home.zip` (Oracle eDelivery / OTN) - Path identic cu DR pentru ca scriptul de restore să funcționeze fără modificări **De ce NU 21c (sau 23ai) la failback:** Tehnic, RMAN 21c **poate** citi backup-uri 19c (controlfile + datafiles + archivelogs se restore). DAR: datafile headers rămân 19c → `ALTER DATABASE OPEN RESETLOGS` eșuează în mod normal. Path-ul corect pe 21c este: ``` RESTORE CONTROLFILE → RESTORE DATABASE → RECOVER DATABASE → STARTUP UPGRADE (NU OPEN normal) → dbupgrade (sau catctl.pl catupgrd.sql) ~30-60 min → ALTER DATABASE OPEN RESETLOGS → @utlrp.sql (recompile invalid objects) → ALTER SYSTEM SET COMPATIBLE='21.0.0' SCOPE=SPFILE (ireversibil, după validare) ``` **Probleme cu acest drum la failback:** - +30-60 min downtime extra în fereastra critică - Pasul de upgrade dictionary nu a fost testat pe acest dataset - Eventuale obiecte/PL-SQL incompatibile descoperite după upgrade — sub presiune - Dacă upgrade-ul eșuează parțial, roll-back complicat (DR e încă opțiune, dar pierzi timp) **Recomandare ferm:** - **Failback acut** → instalează 19c. Identic cu DR. Drum testat săptămânal. Fără surprize. - **Migrare la 21c** → operație separată, planificată, după ce producția e stabilă pe PRIMARY 19c. Două opțiuni: - **DBUA in-place upgrade** 19c → 21c — păstrează DBID, downtime planificat - **Data Pump** (expdp/impdp full) — mai curat, dar pierzi DBID + statistici Scriptul `rman_restore_to_primary.ps1` are check explicit pe major version și abortează dacă găsește ≠ 19, ca să nu se pornească cu jumătate de plan în fereastra de criză. --- ## 1. Precondiții | Cerință | Verificare | |---------|------------| | PRIMARY (10.0.20.36) accesibil pe rețea | `ping 10.0.20.36` | | Oracle 19c instalat pe PRIMARY (versiune identică cu DR) | `sqlplus -V` pe PRIMARY | | `ORACLE_SID=ROA`, `ORACLE_HOME` la aceeași cale ca pe DR | vezi `proxmox/lxc108-oracle/roa-windows-setup/` | | Aplicațiile pot fi puse în mentenanță (downtime ~30 min) | window planificat | | NFS share `oracle-backups` accesibil de pe PRIMARY (sau plan B: copy via SMB/SCP) | `mount -o ... 10.0.20.202:/mnt/pve/oracle-backups F:` | | Cont SYSDBA disponibil pe PRIMARY (proaspăt instalat = `system/manager` sau parola setată la instalare) | `sqlplus / as sysdba` | | Backup ZFS replica pveelite → pve1 a dataset-ului `oracle-backups` rulează | `zfs list -t snapshot \| grep oracle-backups` | --- ## 2. Pași — overview ``` ┌──────────────────────────────────────────────────────────────┐ │ FAZA 1: PREPARE — DR în mentenanță, backup final │ │ 1. Anunț downtime aplicații │ │ 2. Read-only pe DR │ │ 3. RMAN full backup pe DR → NFS │ │ 4. Switch + archivelog pentru tranzacții finale │ ├──────────────────────────────────────────────────────────────┤ │ FAZA 2: RESTORE — restore pe PRIMARY nou │ │ 5. Mount NFS pe PRIMARY (sau copy backup-uri) │ │ 6. Cleanup PRIMARY (dacă reinstalare a creat DB demo) │ │ 7. Rulare rman_restore_to_primary.ps1 │ │ 8. Verify DB OPEN + tabele │ ├──────────────────────────────────────────────────────────────┤ │ FAZA 3: SWITCH — comutare aplicații, reset infra │ │ 9. Update connection strings: 10.0.20.37 → 10.0.20.36 │ │ 10. Test conectivitate aplicații │ │ 11. Reactivează scheduled tasks RMAN backup pe PRIMARY │ │ 12. Stop VM 109 (`qm stop 109`), readuce în `state=stopped`│ │ 13. Verifică ZFS replica + flow nou backup-uri pe NFS │ └──────────────────────────────────────────────────────────────┘ ``` --- ## FAZA 1 — Prepare ### Pas 1: Anunț downtime aplicații Tot traficul de scriere trebuie oprit în timpul backup-ului final. Notifică utilizatorii și planifică un window de ~30 min. ### Pas 2: Read-only pe DR (10.0.20.37) ```sql -- Conectare la DR sqlplus / as sysdba -- Verifică tranzacții active SELECT username, status, count(*) FROM v$session WHERE type='USER' GROUP BY username,status; -- Pune DB în restricted mode (doar SYSDBA poate scrie) ALTER SYSTEM ENABLE RESTRICTED SESSION; -- Sau, mai sigur: read-only mode (necesită shutdown + mount) SHUTDOWN IMMEDIATE; STARTUP MOUNT; ALTER DATABASE OPEN READ ONLY; ``` > **Atenție**: read-only mode oprește scrierile complet, dar și aplicațiile vor primi erori la INSERT/UPDATE. Restricted session e mai blând dacă aplicațiile pot tolera disconectare scurtă. ### Pas 3: RMAN full backup pe DR ```cmd REM Pe DR VM (10.0.20.37) - dacă e încă în restricted/read-only D:\oracle\scripts\rman_backup.bat ``` Backup-ul este scris pe `F:\ROA\autobackup` (NFS mount din `10.0.20.202:/mnt/pve/oracle-backups`). ### Pas 4: Switch + archivelog pentru tranzacții finale Dacă DB e încă în READ WRITE, capturează ultimele archivelogs: ```sql ALTER SYSTEM SWITCH LOGFILE; ALTER SYSTEM ARCHIVE LOG CURRENT; -- Backup archivelog -- în RMAN: RMAN> BACKUP ARCHIVELOG ALL DELETE INPUT; ``` Notează **SCN-ul curent** — necesar pentru verificare ulterioară: ```sql SELECT CURRENT_SCN FROM v$database; -- Notează valoarea, ex: 12345678 ``` ### Pas 5: Verifică backup-urile pe NFS ```bash ssh root@10.0.20.202 "ls -lt /mnt/pve/oracle-backups/ROA/autobackup/ | head -20" ``` Trebuie să vezi backup-urile recente (data/ora din pasul 3-4). --- ## FAZA 2 — Restore pe PRIMARY ### Pas 6: Mount NFS pe PRIMARY (sau copy backup-uri) **Opțiunea A (recomandată): NFS mount direct pe PRIMARY** Pe Windows PRIMARY: ```powershell # Activare NFS Client (o singură dată, dacă nu e instalat) Install-WindowsFeature -Name NFS-Client # Mount NFS share ca F: mount -o anon,nolock,mtype=hard,timeout=60 10.0.20.202:/mnt/pve/oracle-backups F: # Verifică dir F:\ROA\autobackup ``` **Opțiunea B (fallback): Copy via SMB/SCP** Dacă NFS nu funcționează pe PRIMARY (rar): ```powershell # Pe PRIMARY, copy de pe DR VM care are F:\ montat: robocopy \\10.0.20.37\F$\ROA\autobackup F:\ROA\autobackup /MIR /Z ``` ### Pas 7: Cleanup PRIMARY (dacă reinstalare a creat DB demo) Dacă instalarea Oracle a creat o DB demo (ex: ORCL), șterge-o ca să eviți conflicte: ```cmd REM Pe PRIMARY sqlplus / as sysdba SHUTDOWN ABORT; EXIT; oradim -delete -sid ORCL ``` Apoi rulează `cleanup_database.ps1` de pe DR (copiat în prealabil pe PRIMARY) sau doar șterge directoarele oradata/recovery_area existente pentru SID `ROA` (atenție: dacă PRIMARY are un `OracleServiceROA` rezidual de la instalare anterioară, oprește și șterge serviciul cu `oradim -delete -sid ROA`). ### Pas 8: Rulează scriptul de restore ```cmd REM Pe PRIMARY (10.0.20.36) powershell -ExecutionPolicy Bypass -File D:\oracle\scripts\rman_restore_to_primary.ps1 ``` Scriptul `rman_restore_to_primary.ps1` (vezi `proxmox/vm109-windows-dr/scripts/`): - Folosește același DBID `1363569330` - Restore din `F:\ROA\autobackup` - Configurează listener pe `10.0.20.36:1521` - Setează SPFILE și service `OracleServiceROA` pe AUTOMATIC ### Pas 9: Verifică DB ```sql sqlplus / as sysdba SELECT name, open_mode, dbid FROM v$database; -- Așteptat: ROA, READ WRITE, 1363569330 SELECT current_scn FROM v$database; -- Trebuie să fie >= SCN-ul notat în pasul 4 SELECT count(*) FROM dba_tables WHERE owner NOT IN ('SYS','SYSTEM','XDB','GSMADMIN_INTERNAL','APPQOSSYS','OUTLN','DBSNMP','WMSYS','OLAPSYS','MDSYS','CTXSYS','EXFSYS','ORDSYS','LBACSYS'); -- Compară cu count-ul de pe DR (înainte de read-only) -- Test scriere CREATE TABLE test_failback_check (id NUMBER, ts DATE); INSERT INTO test_failback_check VALUES (1, SYSDATE); COMMIT; SELECT * FROM test_failback_check; DROP TABLE test_failback_check PURGE; ``` ### Pas 10: Reset RMAN catalog După `OPEN RESETLOGS`, marchează incarnation-ul nou: ```cmd rman target / RMAN> LIST INCARNATION; RMAN> RESET DATABASE TO INCARNATION ; RMAN> CROSSCHECK BACKUP; RMAN> DELETE NOPROMPT EXPIRED BACKUP; ``` --- ## FAZA 3 — Switch & cleanup ### Pas 11: Update connection strings aplicații Schimbă în toate aplicațiile: ``` ÎNAINTE: 10.0.20.37:1521/ROA (DR) DUPĂ: 10.0.20.36:1521/ROA (PRIMARY restaurat) ``` Locuri de modificat (conform `vm109-windows-dr/README.md`): - Aplicații client (TNS_ADMIN sau connection strings hardcoded) - Reverse proxy IIS (VM 201) — dacă rutează către Oracle - Flowise (LXC 104) — variabile de mediu Oracle - Scheduled tasks/cron-uri ce conectează la Oracle ### Pas 12: Test conectivitate ```bash # De pe Claude Agent (10.0.20.171) sqlplus user/pass@10.0.20.36:1521/ROA # Test din aplicație principală — un read + un write minor ``` ### Pas 13: Reactivează scheduled tasks RMAN pe PRIMARY Pe PRIMARY (Windows Task Scheduler): - `Oracle RMAN Full Backup` — săptămânal (rulează `D:\oracle\scripts\rman_backup.bat`) - `Oracle RMAN Incremental` — zilnic (rulează `D:\oracle\scripts\rman_backup_incremental.bat`) - `Oracle Backup Transfer` — după fiecare backup (rulează `D:\oracle\scripts\transfer_backups.ps1`) Verifică că rulează corect: ```cmd REM Forțează un transfer de test powershell -File D:\oracle\scripts\transfer_backups.ps1 REM Verifică pe Proxmox că au ajuns ssh root@10.0.20.202 "ls -lt /mnt/pve/oracle-backups/ROA/autobackup/ | head -5" ``` ### Pas 14: Oprire VM 109, revenire la state normal ```bash # Pe pveelite ssh root@10.0.20.203 "qm stop 109" # Verifică HA config: VM 109 trebuie să rămână state=stopped, nofailback=1 ssh root@10.0.20.203 "ha-manager config | grep -A2 vm:109" # Așteptat: # state stopped # group ha-prefer-pveelite # nofailback 1 ``` ### Pas 15: Verifică ZFS replicare backup-uri ```bash # Snapshot-urile noi de pe pveelite trebuie să apară pe pve1 ssh root@10.0.20.201 "zfs list -t snapshot rpool/oracle-backups | tail -10" # Verifică job-ul de replicare ssh root@10.0.20.203 "cat /var/log/oracle-dr/replication.log | tail -20" ``` ### Pas 16: Reactivează test săptămânal DR Test-ul săptămânal din cron (Sâmbătă 06:00) va rula automat. Verifică prima rulare după failback ca să confirmi că backup-urile noi de pe PRIMARY sunt restaurabile pe VM 109: ```bash # Sâmbăta următoare, după 06:00 ssh root@10.0.20.203 "ls -lt /var/log/oracle-dr/dr_test_*.log | head -1" # Apoi tail pentru "PASSED" ``` --- ## Roll-back (dacă failback eșuează) Dacă restore pe PRIMARY eșuează sau verificarea găsește lipsuri de date: 1. **NU șterge** baza de pe DR — e încă fallback-ul tău 2. Pune aplicațiile înapoi pe `10.0.20.37:1521/ROA` (DR) 3. Repornește scrierile pe DR (`ALTER SYSTEM DISABLE RESTRICTED SESSION;` sau `STARTUP` normal dacă era read-only) 4. Investigare separată pe PRIMARY — doar după ce înțelegi cauza, încearcă din nou --- ## Anexă A — Diferențe între DR test și failback real | Aspect | DR test săptămânal | Failback real | |--------|---------------------|---------------| | Sursă backup | NFS, ultimele backup-uri din `F:\` | NFS, **backup proaspăt** făcut de DR în pas 3 | | TestMode flag | `-TestMode` (skip listener config) | **NU** TestMode (full config + listener) | | Cleanup post-restore | DA — `cleanup_database.ps1 /AFTER` | **NU** — DB e producția acum | | Stop VM/server după | DA — `qm stop 109` | **NU** — server rămâne up | | Connection strings | nu se schimbă | se schimbă pe PRIMARY | | Scheduled tasks RMAN | nu se ating | se reactivează pe PRIMARY | ## Anexă B — Estimări durată | Pas | Durată estimată | |-----|-----------------| | Pas 2-4: Read-only + final backup pe DR | 5-10 min (depinde mărime DB) | | Pas 6: NFS mount + verify | 2 min | | Pas 7-8: Cleanup + restore script | 15-25 min (RMAN restore din 139 backup files) | | Pas 9-10: Verify + RMAN catalog reset | 5 min | | Pas 11-12: Switch aplicații + test | 5-10 min | | **Total downtime** | **~30-50 min** | --- **Last updated**: 2026-04-25 **Status**: Procedura nu a fost încă executată end-to-end — testează într-un environment de probă (vezi VM 302) înainte de un failback real.