fix(roa): aliasul TNS lipsea din Oracle Home, iar actualizarea esua tacut
Constatat la VADECO pe 2026-08-28: pe serverul acela actualizarea ROA nu aplicase NICIODATA un script, desi jobul raporta succes de la instalare. PACK_UPDATE nu aplica el scripturile - genereaza D:\DMPDIR\script_master.sql si lanseaza un sqlplus EXTERN, apoi se termina. Deci UPDATEROA_ZILNIC raporteaza starea lansarii, nu a actualizarii: SUCCEEDED in ~5 secunde chiar si cand nu s-a aplicat nimic. Scriptul generat incepe cu "CONNECT CONTAFIN_ORACLE/...@ROA" (aliasul vine din NOM_FIRME.NUME_SERVER) si are WHENEVER SQLERROR EXIT, deci iese la prima linie daca aliasul nu se rezolva. Lantul cauzal: sqlplus-ul lansat de baza mosteneste mediul serviciului Oracle. La o instalare noua instanta porneste INAINTE ca 01-setup-database sa scrie TNS_ADMIN de masina, deci serviciul nu il are si cade pe tnsnames.ora din Oracle Home. La 21c XE home-ul e read-only, deci fisierul real e in product\21c\homes\OraDB21Home1\network\admin, iar acolo Oracle genereaza doar XE, LISTENER_XE si ORACLR_CONNECTION_DATA - fara ROA. Rezultat: ORA-12154, tacut. Perfid: tnsping ROA REUSESTE dintr-o sesiune interactiva, pentru ca aceea are TNS_ADMIN. Eroarea era mascata dublu - jobul zicea SUCCEEDED, iar emailul de raportare nu pleaca oricum (ORA-29279, SMTP-ul romfast nu anunta AUTH). 01-setup-database.ps1 scrie acum aliasul si in tnsnames.ora al Oracle Home-ului, cu acelasi IP din LAN. Blocul se IMBINA in fisierul existent: XE, LISTENER_XE si ORACLR_CONNECTION_DATA raman neatinse, pentru ca de ele depind extproc si inregistrarea instantei la listener. Cu backup si idempotent - regexul consuma si comentariile lipite deasupra lui "ROA =", altfel antetul se dubla la fiecare rulare (prins de test). Testat unitar (fisier Oracle fara ROA, idempotenta peste 4 rulari, ROA preexistent cu alt IP la mijloc, fisier inexistent, paranteze echilibrate, fara BOM) si end-to-end pe o copie a fisierului real de pe serverul VADECO: tnsping ROA OK, sqlplus CONTAFIN_ORACLE@ROA conectat in XEPDB1, zero ORA-, XE si LISTENER_XE inca se rezolva. docs/lectii-actualizare-roa-alias-tns.md are diagnosticul complet, inclusiv cum verifici ca actualizarea chiar s-a aplicat: script_master.log si SCHEMA.versiune, NU statusul jobului. Contine si capcana ca randurile din SCHEMA.versiune vin cu dump-ul la import, deci o schema proaspat importata pare la zi fara ca actualizarea sa fi rulat vreodata local. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01X9Sa54oFKpE2XhD6A7NTch
This commit is contained in:
158
docs/lectii-actualizare-roa-alias-tns.md
Normal file
158
docs/lectii-actualizare-roa-alias-tns.md
Normal file
@@ -0,0 +1,158 @@
|
||||
# Actualizarea ROA eșuează tăcut fără aliasul TNS pe server
|
||||
|
||||
**Constatat la VADECO, 2026-08-28.** Pe serverul acela actualizarea ROA **nu aplicase niciodată un
|
||||
script**, deși jobul raporta succes de la instalare. Aceeași defecțiune apare la orice client
|
||||
instalat cu kitul înainte de corecția din `01-setup-database.ps1`.
|
||||
|
||||
## Simptomul
|
||||
|
||||
`DBMS_SCHEDULER.RUN_JOB('CONTAFIN_ORACLE.UPDATEROA_ZILNIC')` se termină în ~5-7 secunde și
|
||||
`dba_scheduler_job_run_details` arată **`SUCCEEDED`, `error#=0`**. Dar:
|
||||
|
||||
- nicio schemă nu primește scripturi noi;
|
||||
- `CONTAFIN_ORACLE.UPD_ISTORIC` rămâne cu un rând `stare=2` deschis (fără `dataora_end`), care
|
||||
blochează rularea următoare;
|
||||
- `SCHEMA.versiune` nu capătă rânduri noi.
|
||||
|
||||
## De ce jobul minte
|
||||
|
||||
`PACK_UPDATE` **nu aplică el scripturile**. El generează `D:\DMPDIR\script_master.sql` și
|
||||
**lansează un `sqlplus.exe` extern**, apoi se termină. Jobul raportează starea *lansării*, nu a
|
||||
actualizării. Scriptul generat începe așa:
|
||||
|
||||
```sql
|
||||
SET AUTOPRINT OFF
|
||||
WHENEVER SQLERROR EXIT SQL.SQLCODE
|
||||
SPOOL D:\DMPDIR\script_master.log
|
||||
CONNECT CONTAFIN_ORACLE/<parola>@ROA
|
||||
```
|
||||
|
||||
Aliasul (`ROA`) vine din **`CONTAFIN_ORACLE.NOM_FIRME.NUME_SERVER`**. Cu `WHENEVER SQLERROR EXIT`,
|
||||
dacă aliasul nu se rezolvă scriptul **iese la prima linie** și nu face absolut nimic — tăcut, pentru
|
||||
că singura urmă e în spool.
|
||||
|
||||
Eșecul e mascat dublu: jobul zice `SUCCEEDED`, iar raportarea pe email e oricum nefuncțională
|
||||
(`ORA-29279: 503 AUTH command used when not advertised` — vezi `docs/handoff_vadeco-update-roa.md`).
|
||||
|
||||
## De ce nu se rezolvă aliasul
|
||||
|
||||
`sqlplus`-ul lansat de bază **moștenește mediul serviciului Oracle**, nu pe al utilizatorului conectat.
|
||||
Lanțul, la o instalare nouă:
|
||||
|
||||
1. Instalarea pornește instanța. În acel moment `TNS_ADMIN` **nu există** încă la nivel de mașină.
|
||||
2. `01-setup-database.ps1` scrie apoi `TNS_ADMIN` (spre `D:\ROA\instantclient_11_2_0_2`) și pune
|
||||
aliasul `ROA` acolo.
|
||||
3. Serviciul Oracle rulează în continuare cu mediul de la pasul 1 — **fără `TNS_ADMIN`**. Efectul
|
||||
variabilei apare abia la primul restart al serviciului.
|
||||
4. Deci `sqlplus`-ul lansat de bază caută `tnsnames.ora` în **Oracle Home**.
|
||||
5. Oracle 21c XE folosește **read-only Oracle Home**: fișierul real e în
|
||||
`...\product\21c\homes\OraDB21Home1\network\admin\`, nu în `dbhomeXE\network\admin\`
|
||||
(acolo e doar `sqlnet.ora.rooh`).
|
||||
6. Fișierul acela e generat de Oracle și conține `XE`, `LISTENER_XE`, `ORACLR_CONNECTION_DATA` —
|
||||
**dar nu `ROA`**. → `ORA-12154`.
|
||||
|
||||
Capcana perfidă: `tnsping ROA` **reușește** dintr-o sesiune interactivă, pentru că sesiunea ta *are*
|
||||
`TNS_ADMIN`. Nimic nu pare greșit până nu te uiți în spool.
|
||||
|
||||
## Diagnostic în 30 de secunde
|
||||
|
||||
Citește spool-ul — el are adevărul, nu jobul:
|
||||
|
||||
```powershell
|
||||
Get-Content D:\DMPDIR\script_master.log
|
||||
```
|
||||
|
||||
Un eșec arată exact așa (fișier de ~100 de octeți):
|
||||
|
||||
```
|
||||
28/08/2026 14:26:59
|
||||
ERROR:
|
||||
ORA-12154: TNS:could not resolve the connect identifier specified
|
||||
```
|
||||
|
||||
Reproducere deterministă, în mediul în care rulează baza (fără `TNS_ADMIN`):
|
||||
|
||||
```powershell
|
||||
Remove-Item Env:TNS_ADMIN -ErrorAction SilentlyContinue
|
||||
"exit" | & "$oraHome\bin\sqlplus.exe" -L -S "CONTAFIN_ORACLE/<parola>@ROA"
|
||||
```
|
||||
|
||||
`ORA-12154` ⇒ actualizarea ROA nu a funcționat niciodată pe serverul acela.
|
||||
|
||||
## Reparația
|
||||
|
||||
Aliasul trebuie să existe **și** în `tnsnames.ora` al Oracle Home-ului, nu doar în cel din
|
||||
`TNS_ADMIN`. Din 2026-08-28, `01-setup-database.ps1` îl scrie în ambele locuri, cu același IP din LAN.
|
||||
|
||||
Manual, pe un server deja instalat:
|
||||
|
||||
```powershell
|
||||
$f = 'D:\app\Administrator\product\21c\homes\OraDB21Home1\network\admin\tnsnames.ora'
|
||||
Copy-Item $f "$f.bak_$(Get-Date -Format yyyyMMdd_HHmmss)"
|
||||
Add-Content -Path $f -Encoding ASCII -Value @"
|
||||
|
||||
ROA =
|
||||
(DESCRIPTION =
|
||||
(ADDRESS = (PROTOCOL = TCP)(HOST = <IP_LAN_SERVER>)(PORT = 1521))
|
||||
(CONNECT_DATA =
|
||||
(SERVER = DEDICATED)
|
||||
(SERVICE_NAME = XEPDB1)
|
||||
)
|
||||
)
|
||||
"@
|
||||
```
|
||||
|
||||
Nu rescrie fișierul întreg: `ORACLR_CONNECTION_DATA` e folosit de extproc, iar `LISTENER_XE` de
|
||||
înregistrarea instanței la listener. Adaugă doar aliasul.
|
||||
|
||||
Nu e nevoie de restart — următorul `sqlplus` lansat de bază citește fișierul la conectare.
|
||||
|
||||
### După reparație
|
||||
|
||||
```sql
|
||||
-- 1. Deblochează rularea rămasă agățată, daca e cazul
|
||||
exec CONTAFIN_ORACLE.PACK_UPDATE.IncheiereActualizare;
|
||||
commit;
|
||||
|
||||
-- 2. Rulează
|
||||
exec DBMS_SCHEDULER.RUN_JOB('CONTAFIN_ORACLE.UPDATEROA_ZILNIC', use_current_session => FALSE);
|
||||
exec DBMS_SCHEDULER.RUN_JOB('CONTAFIN_ORACLE.UPDATERTVAI_ZILNIC', use_current_session => FALSE);
|
||||
```
|
||||
|
||||
## Cum verifici că actualizarea chiar s-a aplicat
|
||||
|
||||
**Nu te uita la statusul jobului.** Dovada reală e în două locuri:
|
||||
|
||||
```powershell
|
||||
# Spool-ul trebuie sa aiba zeci de linii si zero ORA-
|
||||
(Select-String -Path D:\DMPDIR\script_master.log -Pattern 'ORA-|ERROR' | Measure-Object).Count
|
||||
```
|
||||
|
||||
```sql
|
||||
-- Fiecare schema de firma trebuie sa aiba scriptul zilei
|
||||
select max(data_script) from VADECO.versiune;
|
||||
select count(*) from VADECO.versiune where script_final like '%2026_08_28%';
|
||||
|
||||
-- Si nicio rulare agatata
|
||||
select count(*) from CONTAFIN_ORACLE.UPD_ISTORIC where stare = 2; -- trebuie 0
|
||||
```
|
||||
|
||||
> **Atenție la o iluzie:** rândurile din `SCHEMA.versiune` vin **cu dump-ul** la un import. O schemă
|
||||
> proaspăt importată pare „la zi" fără ca actualizarea să fi rulat vreodată local. Compară cu data
|
||||
> scriptului efectiv aplicat azi, nu cu `max(data_script)` în absolut.
|
||||
|
||||
## Capcane conexe, plătite deja
|
||||
|
||||
- `UPD_ISTORIC` are coloanele `DATAORA_START` / `DATAORA_END`, nu `DATA_START`.
|
||||
- `VERSIUNE` are `SCRIPT_FINAL` / `DATA_SCRIPT`, nu `NUME_SCRIPT`.
|
||||
- `UPD_LOG.EXPLICATIE` e `CLOB` și sparge `to_char()` cu `ORA-22835` peste 4000 de caractere.
|
||||
Folosește `dbms_lob.substr(explicatie, 180, 1)`.
|
||||
- Un `stare=2` rămas deschis blochează rularea următoare — de aceea `IncheiereActualizare` e primul
|
||||
pas după orice eșec.
|
||||
|
||||
## Legături
|
||||
|
||||
- Lecții de conectare a clienților vechi (`ORA-28040` / `ORA-01017` / `ORA-12514`):
|
||||
`docs/lectii-conectare-client-oracle.md`
|
||||
- Instalarea și configurarea: `proxmox/lxc108-oracle/roa-windows-setup/README.md`
|
||||
- SMTP-ul nefuncțional care maschează erorile: `docs/handoff_vadeco-update-roa.md`
|
||||
Reference in New Issue
Block a user