Files
ROMFASTSQL/docs/lectii-conectare-client-oracle.md
Marius a5ea8c7ffa fix(oracle): instanta citeste TNS_ADMIN-ul de masina, nu Oracle Home
Continuarea corectiei 3 din ec66377. Aceea rezolva doar jumatatea vizibila a
problemei; jumatatea ascunsa ar fi lovit la primul reboot al serverului, dupa
plecarea de la client. Gasit la VADECO, verificat pe loc.

1. ORA-12514 la toti clientii, cu baza perfect sanatoasa.

   TNS_ADMIN de masina nu decide doar de unde se citeste sqlnet.ora: instanta
   rezolva de acolo si aliasurile din tnsnames.ora. La Oracle XE LOCAL_LISTENER
   e implicit aliasul LISTENER_XE, definit doar in tnsnames.ora din Oracle Home.
   Cand serviciul reporneste dupa ce ROAClient a pus TNS_ADMIN pe folderul
   instantclient-ului, aliasul nu se mai rezolva, instanta nu se mai
   inregistreaza la listener, si atunci: v$instance OPEN, v$pdbs READ WRITE,
   listener pornit pe 0.0.0.0:1521, lsnrctl arata doar CLRExtProc, si absolut
   orice client primeste ORA-12514.

   Capcana e de timp, nu de continut: o instanta pornita inainte ca TNS_ADMIN
   sa existe nu il vede, deci instalarea pare impecabila si cade la primul
   reboot. Reprodus la VADECO cu un simplu Restart-Service OracleServiceXE.

   Pasul 01 scrie acum si tnsnames.ora in TNS_ADMIN (aliasul ROA pentru
   ROAClient - sablonul livrat cu el arata spre HOST=SERVER_ROA, inexistent -
   plus LISTENER_XE pentru instanta) si, mai important, fixeaza LOCAL_LISTENER
   pe adresa literala. Doar asta din urma rezista si daca ROAClient se
   instaleaza dupa kit, sau daca folderul instantclient se muta.

2. ORA-01017 desi parola e corecta.

   Cu SQLNET.ALLOWED_LOGON_VERSION_SERVER=8 serverul autentifica orice client
   pre-12c pe baza verificatorului 10G. Un cont fara 10G in PASSWORD_VERSIONS
   nu se mai poate conecta din Instant Client 10/11, si eroarea nu e ORA-28040,
   ci ORA-01017 - fix cea care trimite pe pista parolei. Dupa o instalare 21c,
   SYSTEM are doar 11G 12C; CONTAFIN_ORACLE scapa doar pentru ca pasul 01 ii
   rescrie parola dupa ce a scris sqlnet.ora. Pasul 01 rescrie acum si parola
   lui SYSTEM, din CDB$ROOT, cu aceeasi valoare.

   Subtilitate: interogat din PDB, PASSWORD_VERSIONS al unui utilizator comun
   ramane cel vechi si dupa reparatie, desi autentificarea foloseste definitia
   din root si functioneaza. Coloana nu e o dovada pentru SYSTEM; conectarea e.

3. Pasul 07 verifica acum ce nu se vede pe hartie.

   Toate cele trei erori trec de verificarile de pana acum: fisierul exista,
   parametrul e setat, contul e OPEN, obiectele sunt valide. Sectiunea noua
   "Conectivitate client vechi (Instant Client)" verifica unde se citeste
   efectiv sqlnet.ora, daca tnsnames.ora din TNS_ADMIN mai e sablonul, daca
   LOCAL_LISTENER e alias sau adresa, ce verificatoare de parola au conturile,
   si - singurul lucru care le prinde pe toate - face o conectare adevarata cu
   Instant Client-ul gasit pe masina. La esec, raportul spune si unde sa te
   uiti. Parametri noi: -ContafinPassword, -InstantClientDir.

4. Get-ServerLanIPv4, in biblioteca.

   Pe serverele la care intram prin Tailscale, un tnsnames.ora cu 100.x nu duce
   nicaieri de pe o statie. Functia alege IP-ul din LAN sarind peste Tailscale
   (100.64.0.0/10) si APIPA, dupa ruta implicita cand sunt mai multe placi.
   Get-ListenerHost o foloseste si el la fallback-ul pe 0.0.0.0, unde inainte
   lua prima adresa nefiltrata.

La VADECO a mai fost nevoie de o corectie manuala, in afara kitului: listener.ora
avea HOST = <nume>.ts.net, deci pornirea listenerului depindea de Tailscale.
Regula generala e in documentatie.

Detaliile, cu dovezi si comenzi de diagnostic: docs/lectii-conectare-client-oracle.md

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SzF1hf4aFS1tmJWpPMiwGp
2026-08-25 22:14:45 +03:00

11 KiB
Raw Permalink Blame History

Lecții — conectarea clienților vechi (Instant Client 10/11) la Oracle 21c

Scris pe 2026-08-25, după migrarea VADECO pe server nou. Toate lucrurile de mai jos au fost observate direct, nu deduse din documentație, iar fiecare a fost verificat pe serverul clientului (WIN-16COB435C1E, 192.168.101.111, Oracle XE 21.3, CDB XE + PDB XEPDB1).

Numitorul comun al tuturor: niciuna dintre erori nu arată spre cauza ei. ORA-01017 pare parolă greșită, ORA-12514 pare baza oprită, ORA-28040 pare o problemă de client. De aceea au ajuns aici, într-un fișier separat.


1. TNS_ADMIN de mașină bate Oracle Home — și pentru instanță, nu doar pentru clienți

ROAClient își pune TNS_ADMIN de mașină pe folderul propriului Instant Client (la VADECO: d:\roa\instantclient_11_2_0_2). Variabila nu e citită doar de sqlplus-ul din folderul acela: serviciul Oracle o moștenește la pornire, iar procesele bazei citesc de acolo și sqlnet.ora, și tnsnames.ora.

Capcana e de timp, nu de conținut. O instanță pornită înainte ca TNS_ADMIN să existe nu o vede, deci continuă să citească din Oracle Home și totul pare în regulă. Efectul apare abia la primul restart al serviciului — adică la primul reboot al serverului, de obicei după ce am plecat de la client.

1a. Fără sqlnet.ora acolo → ORA-28040 la toți clienții vechi

SQLNET.ALLOWED_LOGON_VERSION_SERVER=8 scris frumos în ORACLE_BASE_HOME\network\admin\sqlnet.ora devine irelevant: instanța citește din TNS_ADMIN, nu găsește nimic, cade pe implicitul 21c (12) și refuză orice client pre-12c.

1b. Fără tnsnames.ora acolo → ORA-12514 la toți clienții

Asta e cea gravă, și e cea pe care am prins-o efectiv. La Oracle XE, LOCAL_LISTENER e implicit aliasul LISTENER_XE, definit numai în tnsnames.ora din Oracle Home. După restart, instanța încearcă să rezolve aliasul din TNS_ADMIN-ul nou, nu-l găsește, nu se mai înregistrează la listener — și atunci:

  • baza e sus (v$instance = OPEN, v$pdbs = READ WRITE);
  • serviciul Windows e Running;
  • listenerul e Running și ascultă pe 0.0.0.0:1521;
  • lsnrctl status arată doar CLRExtProc;
  • absolut orice client primește ORA-12514.

Adică: server aparent perfect, aplicație complet moartă. Exact ce s-ar fi întâmplat la VADECO la primul reboot.

Reparația

Trei lucruri, toate făcute acum de 01-setup-database.ps1:

  1. sqlnet.ora scris și în TNS_ADMIN, identic cu cel din Oracle Home;
  2. tnsnames.ora scris în TNS_ADMIN, cu aliasul ROA (pentru ROAClient) și LISTENER_XE (pentru instanță);
  3. LOCAL_LISTENER fixat pe adresă literală, ca să nu mai depindă de niciun fișier de rețea:
ALTER SYSTEM SET LOCAL_LISTENER='(ADDRESS=(PROTOCOL=TCP)(HOST=192.168.101.111)(PORT=1521))' SCOPE=BOTH;
ALTER SYSTEM REGISTER;

Punctul 3 e singurul care rezistă și dacă ROAClient se instalează după kit, sau dacă cineva mută folderul Instant Client. Punctele 1 și 2 rămân necesare pentru sqlnet.ora și pentru aliasul ROA, dar au aceeași fragilitate: sunt corecte doar față de valoarea lui TNS_ADMIN din momentul rulării. De asta pasul 07 le reverifică.

Diagnostic rapid

[Environment]::GetEnvironmentVariable('TNS_ADMIN','Machine')
Test-Path "$([Environment]::GetEnvironmentVariable('TNS_ADMIN','Machine'))\sqlnet.ora"
& "$env:ORACLE_HOME\bin\lsnrctl.exe" status | Select-String 'Service "'

Dacă lsnrctl status nu listează serviciul PDB-ului dar baza e OPEN, e exact cazul 1b. Confirmarea:

SELECT value FROM v$parameter WHERE name = 'local_listener';

Un alias (LISTENER_XE) în loc de un (ADDRESS=...) = bombă cu ceas.


2. ALLOWED_LOGON_VERSION_SERVER=8 cere verificator 10G, altfel ORA-01017

Cu setarea asta, serverul autentifică orice client pre-12c pe baza verificatorului 10G. Un cont care nu are 10G în PASSWORD_VERSIONS nu se mai poate conecta din Instant Client 10/11 — și eroarea nu e ORA-28040, e:

ORA-01017: invalid username/password; logon denied

Adică fix eroarea care te trimite să verifici parola. Parola e corectă: același cont, aceeași parolă, se conectează perfect din sqlplus-ul 21c de pe server.

După o instalare curată de 21c, SYSTEM are doar 11G 12C. CONTAFIN_ORACLE are 10G 11G 12C doar pentru că pasul 01 îi rescrie parola după ce a scris sqlnet.ora — verificatoarele se generează după setarea activă în momentul CREATE/ALTER USER, nu retroactiv.

Reparația

Rescrierea aceleiași parole. Nu se schimbă nimic pentru nimeni, doar se regenerează verificatoarele:

-- utilizator local (schemele de firmă, CONTAFIN_ORACLE) — din PDB
ALTER USER CONTAFIN_ORACLE IDENTIFIED BY "ROMFASTSOFT";

-- utilizator comun (SYSTEM) — obligatoriu din CDB$ROOT
ALTER USER SYSTEM IDENTIFIED BY "romfastsoft" CONTAINER=ALL;

Pasul 01 face acum ambele.

Sub-capcană: PASSWORD_VERSIONS minte pentru utilizatorii comuni

Interogat din PDB, DBA_USERS.PASSWORD_VERSIONS pentru SYSTEM rămâne 11G 12C și după ALTER USER ... CONTAINER=ALL din root. Rândul local nu se împrospătează, dar autentificarea folosește definiția din root — și funcționează.

Măsurat la VADECO, în aceeași secundă:

PASSWORD_VERSIONS
CDB$ROOT 10G 11G 12C
XEPDB1 11G 12C
conectare reală din Instant Client 11.2 merge

Concluzie: pentru utilizatorii comuni, coloana nu e o dovadă. Singura verificare validă e o conectare adevărată. De asta pasul 07 nu se mai uită la coloană pentru SYSTEM, ci îl probează.


3. listener.ora legat de un nume care depinde de Tailscale

Instalarea de Oracle a pus în listener.ora și tnsnames.ora:

(ADDRESS = (PROTOCOL = TCP)(HOST = vadeco-server.tailf7372d.ts.net)(PORT = 1521))

Adică numele MagicDNS al mașinii în tailnet. Ascultarea în sine e corectă (listenerul se leagă tot pe 0.0.0.0:1521, deci LAN-ul e servit), dar pornirea listenerului ajunge să depindă de Tailscale: la boot, dacă tailscaled nu a ridicat încă resolverul, numele nu se rezolvă.

Înlocuit cu numele mașinii, care se rezolvă local întotdeauna:

(ADDRESS = (PROTOCOL = TCP)(HOST = WIN-16COB435C1E)(PORT = 1521))

Verificat după restartul listenerului: tot 0.0.0.0:1521, toate serviciile înregistrate, clienții se conectează.

Regulă: pe serverele la care intrăm prin Tailscale, niciun fișier de configurare Oracle nu are voie să conțină un nume *.ts.net sau o adresă 100.64.0.0/10. Din același motiv, Get-ServerLanIPv4 (în scripts/lib/oracle-functions.ps1) sare peste intervalul Tailscale când alege IP-ul pentru tnsnames.ora și LOCAL_LISTENER — un tnsnames.ora cu 100.x copiat pe o stație nu duce nicăieri, stația nu e în tailnet.


4. Proba de conectare cu clientul vechi e obligatorie

Toate cele trei probleme de mai sus trec de verificările „pe hârtie": fișierul există, parametrul e setat, contul e OPEN, obiectele sunt valide. Singurul lucru care le prinde pe toate e o conectare adevărată, cu clientul vechi, nu cu sqlplus-ul 21c de pe server.

$ic = 'D:\ROA\instantclient_11_2_0_2'
'select ''PROBA_OK '' || user from dual;' , 'exit' | Set-Content -Encoding ascii C:\Windows\Temp\t.sql

# prin aliasul din tnsnames.ora — asa se conecteaza ROAClient
& "$ic\sqlplus.exe" -S -L "CONTAFIN_ORACLE/ROMFASTSOFT@ROA" '@C:\Windows\Temp\t.sql'

# prin EZConnect, pe IP-ul din LAN — ocoleste tnsnames.ora, izoleaza cauza
& "$ic\sqlplus.exe" -S -L "CONTAFIN_ORACLE/ROMFASTSOFT@//192.168.101.111:1521/XEPDB1" '@C:\Windows\Temp\t.sql'

-L (o singură încercare) nu e opțional: fără el, la o parolă refuzată sqlplus cere parola de la tastatură și agață o sesiune neinteractivă până la timeout.

Diferența dintre cele două forme e utilă la diagnostic: dacă EZConnect merge și aliasul nu, problema e în tnsnames.ora; dacă niciuna nu merge, problema e la server (verificator de parolă, sqlnet.ora sau înregistrarea la listener).


5. Ce verifică acum pasul 07

07-verify-installation.ps1 a primit secțiunea „Conectivitate client vechi (Instant Client)", care acoperă toate lecțiile de mai sus:

Verificare Prinde
ALLOWED_LOGON_VERSION_SERVER din sqlnet.ora de Oracle Home valoare > 11
sqlnet.ora există în TNS_ADMIN de mașină 1a — ORA-28040 la primul reboot
tnsnames.ora din TNS_ADMIN: alias ROA, LISTENER_XE, urme de șablon (SERVER_ROA) 1b — ORA-12514 la primul reboot; stații care nu găsesc baza
LOCAL_LISTENER e adresă literală, nu alias 1b, cazul de fond
PASSWORD_VERSIONS conține 10G pentru CONTAFIN_ORACLE și schemele de firmă 2 — ORA-01017
conectare reală cu Instant Client-ul găsit pe mașină: CONTAFIN_ORACLE prin alias și prin EZConnect, SYSTEM prin EZConnect tot ce a scăpat

La eșec, raportul spune și unde să te uiți: ORA-01017 → verificatorul 10G, ORA-28040 → TNS_ADMIN, ORA-12514 → LOCAL_LISTENER.

Parametri noi: -ContafinPassword (implicit ROMFASTSOFT) și -InstantClientDir (implicit: din TNS_ADMIN, altfel căutat sub D:\ROA, C:\ROA, D:\, C:\). Dacă nu există Instant Client pe server, proba se raportează ca sărită, nu ca eșec.


6. Capcane de mediu, plătite deja

  • powershell -Command - prin SSH trunchiază scriptul. Un script cu blocuri pe mai multe linii trimis pe stdin se execută parțial: comenzile de după primul bloc multi-linie pur și simplu nu rulează, fără nicio eroare. Se pierde timp crezând că o comandă a eșuat. Soluția: scp fișierul .ps1 și ssh ... powershell -NoProfile -ExecutionPolicy Bypass -File C:\Windows\Temp\x.ps1.
  • sqlplus / as sysdba nu merge într-o sesiune SSH pe serverul ăsta (ORA-01017) — autentificarea pe sistem de operare nu primește token-ul de grup. Se folosește sys/<parola>@//localhost:1521/XE as sysdba, sau bequeath cu ORACLE_SID setat și parolă explicită.
  • Un Restart-Service OracleServiceXE durează 2–4 minute (oprire + pornire + înregistrare). Comenzile de la distanță au nevoie de timeout pe măsură; altfel timeout-ul taie sesiunea în mijlocul unui restart.

Legături

  • Kit și flux complet: proxmox/lxc108-oracle/roa-windows-setup/README.md
  • Migrarea VADECO: docs/handoff_vadeco-migrare.md (nu intră în git)
  • Capcana cu discul C: de pe același server: aceeași migrare, secțiune separată în handoff — procesul Oracle nu ajunge la nicio cale de pe C: